home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / viewers / polyview / polyvw31.lha / Polyview3.1 / new / pvpoly.c < prev    next >
C/C++ Source or Header  |  1993-08-24  |  102KB  |  3,266 lines

  1. /*****************************************************************************
  2.  * NCSA Polyview 3.1                                                         *
  3.  *                                                                           *
  4.  * Version 3.1 changes and additions by Gilles Bourhis.                      *
  5.  * Version 3 changes and additions by Marc Andreessen.                       *
  6.  * Version 2 by Brian Calvert.                                               *
  7.  *                                                                           *
  8.  * Software Development Group                                                *
  9.  * National Center for Supercomputing Applications                           *
  10.  * University of Illinois at Urbana-Champaign                                *
  11.  *                                                                           *
  12.  * This is BETA release software.  As such it may contain software bugs and  *
  13.  * exhibit inconsistencies.                                                  *
  14.  *                                                                           *
  15.  * Please send bug reports to polyview@ncsa.uiuc.edu.                        *
  16.  *                                                                           *
  17.  * Copyright (c) 1992 The Board of Trustees of the University of Illinois.   *
  18.  *                                                                           *
  19.  * Permission to use, copy, and modify this software and its                 *
  20.  * documentation for educational, research, and non-profit purposes is       *
  21.  * hereby granted, provided that the above copyright notice, the original    *
  22.  * authors names, and this permission notice appear in all such copies.      *
  23.  * Any distribution of this software requires the explicit and written       *
  24.  * authorization of the authors.                                             *
  25.  *                                                                           *
  26.  * The University of Illinois makes no representations about the             *
  27.  * suitability of this software for any purpose.  It is provided "as is"     *
  28.  * without warranty of any kind.                                             *
  29.  *****************************************************************************/
  30.  
  31. /* $Id: pvpoly.c,v 1.5 93/08/24 10:28:53 gbourhis Exp $ */
  32.  
  33. #ifdef RCSLOG
  34. $Log:    pvpoly.c,v $
  35.  * Revision 1.5  93/08/24  10:28:53  gbourhis
  36.  * Add "Credits" entry in Props menu.
  37.  * 
  38.  * Revision 1.4  93/08/13  12:46:55  gbourhis
  39.  * Add handling of the "Save RGB" dialog box. Better transcript. Change
  40.  * Version Number
  41.  * 
  42.  * Revision 1.3  93/07/13  16:42:47  gbourhis
  43.  * move and use delete_poly(). When close with OK the sphere stuff window,
  44.  * check if the sphere has been modified by the user.
  45.  * 
  46.  * Revision 1.2  93/06/24  16:32:39  gbourhis
  47.  * add remote_movecursor & remote_movecursorend functions
  48.  * 
  49.  * Revision 1.1  1992/09/18  10:55:26  marca
  50.  * Initial revision
  51.  *
  52. #endif
  53.  
  54. #include "pv.h"
  55. #include <X11/keysym.h>
  56.  
  57. #define PI 3.14159265
  58.  
  59. /* This should be moved. */
  60.  
  61. #ifdef __sgi
  62.  
  63. static Boolean use_pups = FALSE;
  64.  
  65. /* Return the overlay window of the widget. */
  66. static Window overlayWindow(Widget w)
  67. {
  68.   Arg args[1];
  69.   Window overlayWindow;
  70.   
  71.   XtSetArg(args[0], use_pups?GlxNpopupWindow:GlxNoverlayWindow,
  72.            &overlayWindow);
  73.   XtGetValues(w, args, 1);
  74.   return (overlayWindow);
  75. }
  76.  
  77. static XmxCallback (overlayExposeCB)
  78. {
  79.   GLXwinset (XtDisplay (w), ((GlxDrawCallbackStruct *)call_data)->window);
  80.   color (0);
  81.   clear ();
  82.  
  83.   return;
  84. }
  85.  
  86. #endif /* __sgi */
  87.  
  88.  
  89.  
  90. /* --------------------------- dither routines ---------------------------- */
  91. /* Shade pattern masks.  Range from 0 through 100% by 6.25% intervals. */
  92. static unsigned short ShadePattern[18][16];
  93.  
  94. /* DitherMatrix and CreateShadePattern adapted from Peter Burger and Duncan */
  95. /* Gillies, "Interactive Computer Graphics", Addison-Wesley, 1989. */
  96. static short DitherMatrix[4][4] = {
  97.   {1, 9, 3, 11},
  98.   {13, 5, 15, 7},
  99.   {4, 12, 2, 10},
  100.   {16, 8, 14, 6}
  101. };
  102.  
  103. static void CreateShadePatterns()
  104. {
  105.   int i, row;
  106.   short sval, val;
  107.   
  108.   /* Create a total of 18 levels of shading. */
  109.   for (i = 0; i <= 17; i++) 
  110.     {
  111.       /* For each row of the DitherMatrix, calculate the row */
  112.       /* value for the appropriate ShadePattern rows. */
  113.       for (row = 0; row < 4; row++) 
  114.         {
  115.           /* Build the DitherMatrix row value. */
  116.           sval = ((DitherMatrix[row][0]<=i)?0x8:0x0) |
  117.             ((DitherMatrix[row][1]<=i)?0x4:0x0) |
  118.               ((DitherMatrix[row][2]<=i)?0x2:0x0) |
  119.                 ((DitherMatrix[row][3]<=i)?0x1:0x0);
  120.           
  121.           /* Build the value into a full ShadePattern row */
  122.           val = (((((sval<<4)|sval)<<4)|sval)<<4)|sval;
  123.           
  124.           /* Store the value in the appropriate rows of the */
  125.           /* ShadePattern array. */
  126.           ShadePattern[i][row] = val;
  127.           ShadePattern[i][row+4] = val;
  128.           ShadePattern[i][row+8] = val;
  129.           ShadePattern[i][row+12] = val;
  130.         }
  131.     }
  132. }
  133.  
  134. /* Create patterns that are used by various windows.  Patterns */
  135. /* 1 through 18 are 0% through 100% solid screens.  Pattern 0 is */
  136. /* already a solid pattern. */
  137. void init_patterns (void)
  138. {
  139.   int i;
  140.   CreateShadePatterns();
  141.   for (i = 0; i <= 17; i++)
  142.     defpattern(i+1, 16, ShadePattern[i]);
  143. }
  144.  
  145.  
  146.  
  147. /* ------------------------------- best_fit ------------------------------- */
  148. static int best_fit (state_t *state, window_t *win)
  149. {
  150.   float tan_value, va_rad;
  151.   
  152.   va_rad = (PI/180.0) * (WIN_FOV(win)/(20.0));
  153.   tan_value = 2*ftan(va_rad);
  154.   
  155.   /* Adjust rho sufficiently to allow the worst-case view to fit */
  156.   /* within the win.  The worst-case view has a width of */
  157.   /* WIN_MAXWIDTH(). */
  158.   WIN_SFROM(win)[RHO] = WIN_MAXWIDTH(win) / tan_value;
  159.   
  160.   /* Adjust the coordinates back to cartesian space. */
  161.   sphere_to_cart(WIN_SFROM(win)[RHO], WIN_SFROM(win)[THETA],
  162.                  WIN_SFROM(win)[PHI],
  163.                  &(WIN_CFROM(win)[X]), &(WIN_CFROM(win)[Y]),
  164.                  &(WIN_CFROM(win)[Z]) );
  165.   WIN_CFROM(win)[X] += WIN_AT(win)[X];
  166.   WIN_CFROM(win)[Y] += WIN_AT(win)[Y];
  167.   WIN_CFROM(win)[Z] += WIN_AT(win)[Z];
  168.   
  169.   return TRUE;
  170. }
  171.  
  172.  
  173.  
  174. /* ---------------------------- init_polyview ----------------------------- */
  175. /* init_polyview initializes the internals of the polyview data structure. */
  176. /* This function is called when a new polyview is created or the data */
  177. /* associated with the window changes.  The function requires a pointer */
  178. /* to the system state, the window to initialize, and whether to do a reset */
  179. /* or not.  Returns ST_OKAY if no error occurs. */
  180. int init_polyview(state_t *state, window_t *win, int reset)
  181. {
  182.   /* Make sure that there is a structure to initialize. */
  183.   assert (win != NULL);
  184.   
  185.   /* We go through here twice for some reason, for the first window.
  186.      The first time all the stats are max=BIG and min=0, so maxwidth
  187.      makes no sense.  The second time through, they're OK, but by then
  188.      it's too late to change move_step. */
  189.   
  190.   /* Calculate maximum possible width of view. */
  191.   WIN_MAXWIDTH(win) =
  192.     fhypot(WIN_STATS(win,PX).max -
  193.            WIN_STATS(win,PX).min,
  194.            fhypot(WIN_STATS(win,PY).max -
  195.                   WIN_STATS(win,PY).min,
  196.                   WIN_STATS(win,PZ).max -
  197.                   WIN_STATS(win,PZ).min));
  198.   
  199.   if (WIN_MAXWIDTH(win) < FLT_MAX)
  200.     WIN_STEP(win) = WIN_MAXWIDTH(win) * 0.05;  /* was 0.025 */
  201.   else
  202.     WIN_STEP(win) = 0.1;
  203.   
  204.   /* If the view is to be reset, recalculate the best view of */
  205.   /* the data.  This means resetting the reference point, */
  206.   /* resetting the fov angle, placing the camera in the */
  207.   /* positive y direction from the focus point, and calculating */
  208.   /* a best-fit viewing distance. */
  209.   if (reset)
  210.     {
  211.       /* Calculate a new reference point. */
  212.       WIN_AT(win)[X] = (WIN_STATS(win,PX).min +
  213.                         WIN_STATS(win,PX).max) * 0.5;
  214.       WIN_AT(win)[Y] = (WIN_STATS(win,PY).min +
  215.                         WIN_STATS(win,PY).max) * 0.5;
  216.       WIN_AT(win)[Z] = (WIN_STATS(win,PZ).min +
  217.                         WIN_STATS(win,PZ).max) * 0.5;
  218.       
  219.       /* Reset the fov angle. */
  220.       WIN_FOV(win) = DEF_FOV;
  221.       WIN_PROJECTION(win) = PERSPECTIVE;
  222.       
  223.       /* Calculate a new camera point. */
  224.       WIN_SFROM(win)[RHO] = 1.0;
  225.       WIN_SFROM(win)[THETA] = (90.0*PI)/180.0;
  226.       WIN_SFROM(win)[PHI] = (90.0*PI)/180.0;
  227.       
  228.       WIN_TWIST(win) = 0;
  229.       win->twist_tmp = 0;
  230.       
  231.       /* Pick all of the objects. */
  232.       PickAll(state, win);
  233.       
  234.       /* best fit moves the camera along its current */
  235.       /* line of sight to a position which guarantees */
  236.       /* that the entire object will be visible.  It */
  237.       /* modifies both the cartesian and spherical */
  238.       /* representations of the coordinates. */
  239.       best_fit(state, win);
  240.       
  241.       /* should the init_window routine do this? */
  242.       WIN_MOVE(win) = FROM;
  243.     }
  244.   else 
  245.     {
  246.       /* Set up the default names of the data sets. */
  247.       strcpy(WIN_PXNAME(win), DEF_PXNAME);
  248.       strcpy(WIN_PYNAME(win), DEF_PYNAME);
  249.       strcpy(WIN_PZNAME(win), DEF_PZNAME);
  250.       strcpy(win->vname[PCOORD], "pcoord");
  251.       strcpy(WIN_PLISTNAME(win), DEF_CONNECTNAME);
  252.       strcpy(WIN_VSCALARNAME(win), DEF_VSCALARNAME);
  253.       
  254.       /* When shadow data is displayed, use vertices. */
  255.       set_over_shadow_vertices(state, win);
  256.     }
  257.   
  258.   return ST_OKAY;
  259. }
  260.  
  261.  
  262. /* ---------------------------- backdrop code ----------------------------- */
  263. static void DrawBackgroundPolygon (window_t *win, 
  264.                                    int c1, int c2, int c3, int c4)
  265. {
  266.   float vv[2];
  267.  
  268.   zbuffer (FALSE);
  269.   shademodel (GOURAUD);
  270.   mmode (MSINGLE);
  271.   pushmatrix ();
  272.   ortho2 (0.0, 1.0, 0.0, 1.0);
  273.   
  274.   bgnpolygon ();
  275.   vv[0] = 0.0;
  276.   vv[1] = 0.0;
  277.   cpack (c1);  v2f (vv);
  278.   cpack (c2);  vv[0] = 1.0;  v2f (vv);
  279.   cpack (c3);  vv[1] = 1.0;  v2f (vv);
  280.   cpack (c4);  vv[0] = 0.0;  v2f (vv);
  281.   endpolygon ();
  282.  
  283.   popmatrix ();
  284.   mmode (MVIEWING);
  285.   shademodel (WIN_SHADE(win));
  286.   zbuffer (TRUE);
  287.   
  288.   return;
  289. }
  290.  
  291.  
  292. static void draw_backdrop (window_t *win)
  293. {
  294.   /* This handles clearing the window now too. */
  295.   switch (win->backdrop)
  296.     {
  297.     case PV_PALETTE_BACKG_BLACK:
  298.       czclear(0, gstate->zmin);
  299.       break;
  300.     case PV_PALETTE_BACKG_WHITE:
  301.       czclear(0xffffff, gstate->zmin);
  302.       break;
  303.     case PV_PALETTE_BACKG_GREY:
  304.       czclear(0x6f6f6f, gstate->zmin);
  305.       break;
  306.     case PV_PALETTE_BACKG_BLUE:
  307.       czclear(0x9f0000, gstate->zmin);
  308.       break;
  309.     case PV_PALETTE_BACKG_RED:
  310.       czclear(0x00009f, gstate->zmin);
  311.       break;
  312.       
  313.     case PV_PALETTE_BACKG_RGBY:
  314.       czclear(0, gstate->zmin);
  315.       DrawBackgroundPolygon (win, 0x0000ff, 0x00ffff, 0x00ff00, 0xff0000);
  316.       break;
  317.     case PV_PALETTE_BACKG_RGBLUE:
  318.       czclear(0, gstate->zmin);
  319.       DrawBackgroundPolygon (win, 0x00ff00, 0xff0000, 0x0000ff, 0x0000ff);
  320.       break;
  321.     case PV_PALETTE_BACKG_RBBLACK:
  322.       czclear(0, gstate->zmin);
  323.       DrawBackgroundPolygon (win, 0xff0000, 0x0000ff, 0x0, 0x0);
  324.       break;
  325.       
  326.     case PV_PALETTE_BACKG_BLUEHORIZ:
  327.       czclear(0, gstate->zmin);
  328.       DrawBackgroundPolygon (win, 0x9f0000, 0x9f0000, 0x0, 0x0);
  329.       break;
  330.     case PV_PALETTE_BACKG_REDHORIZ:
  331.       czclear(0, gstate->zmin);
  332.       DrawBackgroundPolygon (win, 0x00009f, 0x00009f, 0x0, 0x0);
  333.       break;
  334.     case PV_PALETTE_BACKG_GREENHORIZ:
  335.       czclear(0, gstate->zmin);
  336.       DrawBackgroundPolygon (win, 0x009f00, 0x009f00, 0x0, 0x0);
  337.       break;
  338.     case PV_PALETTE_BACKG_YELLOWHORIZ:
  339.       czclear(0, gstate->zmin);
  340.       DrawBackgroundPolygon (win, 0x009f9f, 0x009f9f, 0x0, 0x0);
  341.       break;
  342.       
  343.     case PV_PALETTE_BACKG_BLUESKY:
  344.       czclear(0, gstate->zmin);
  345.       DrawBackgroundPolygon (win, 0x0, 0x0, 0x9f0000, 0x9f0000);
  346.       break;
  347.     case PV_PALETTE_BACKG_REDSKY:
  348.       czclear(0, gstate->zmin);
  349.       DrawBackgroundPolygon (win, 0x0, 0x0, 0x00009f, 0x00009f);
  350.       break;
  351.     case PV_PALETTE_BACKG_GREENSKY:
  352.       czclear(0, gstate->zmin);
  353.       DrawBackgroundPolygon (win, 0x0, 0x0, 0x009f00, 0x009f00);
  354.       break;
  355.     case PV_PALETTE_BACKG_YELLOWSKY:
  356.       czclear(0, gstate->zmin);
  357.       DrawBackgroundPolygon (win, 0x0, 0x0, 0x009f9f, 0x009f9f);
  358.       break;
  359.       
  360.     case PV_PALETTE_BACKG_BLUESTREAK:
  361.       czclear(0, gstate->zmin);
  362.       DrawBackgroundPolygon (win, 0x0, 0x9f0000, 0x0, 0x9f0000);
  363.       break;
  364.     case PV_PALETTE_BACKG_REDSTREAK:
  365.       czclear(0, gstate->zmin);
  366.       DrawBackgroundPolygon (win, 0x0, 0x00009f, 0x0, 0x00009f);
  367.       break;
  368.     case PV_PALETTE_BACKG_GREENSTREAK:
  369.       czclear(0, gstate->zmin);
  370.       DrawBackgroundPolygon (win, 0x0, 0x009f00, 0x0, 0x009f00);
  371.       break;
  372.     case PV_PALETTE_BACKG_YELLOWSTREAK:
  373.       czclear(0, gstate->zmin);
  374.       DrawBackgroundPolygon (win, 0x0, 0x009f9f, 0x0, 0x009f9f);
  375.       break;
  376.  
  377.     case PV_PALETTE_BACKG_BLUESMEAR:
  378.       czclear(0, gstate->zmin);
  379.       DrawBackgroundPolygon (win, 0x9f0000, 0x0, 0x9f0000, 0x0);
  380.       break;
  381.     case PV_PALETTE_BACKG_REDSMEAR:
  382.       czclear(0, gstate->zmin);
  383.       DrawBackgroundPolygon (win, 0x00009f, 0x0, 0x00009f, 0x0);
  384.       break;
  385.     case PV_PALETTE_BACKG_GREENSMEAR:
  386.       czclear(0, gstate->zmin);
  387.       DrawBackgroundPolygon (win, 0x009f00, 0x0, 0x009f00, 0x0);
  388.       break;
  389.     case PV_PALETTE_BACKG_YELLOWSMEAR:
  390.       czclear(0, gstate->zmin);
  391.       DrawBackgroundPolygon (win, 0x009f9f, 0x0, 0x009f9f, 0x0);
  392.       break;
  393.     }
  394.  
  395.   return;
  396. }
  397.  
  398.  
  399.  
  400. /* --------------------------- redraw_polyview ---------------------------- */
  401. int redraw_polyview(state_t *state, window_t *win)
  402. {
  403.   polyview_t *pv;
  404.   object_t *obj;
  405.   int status;
  406.   float    maxwidth;
  407.   static Matrix    ident = {
  408.     {1.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0}, 
  409.     {0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 1.0}
  410.   };
  411.   int i, j;
  412.   float    xaspect, yaspect;
  413.   float width, height;
  414.   Matrix op;
  415.  
  416.   /* Get a pointer to the root object associated with the win. */
  417.   pv = (polyview_t *)WIN_IMAGE(win);
  418.  
  419.   /* We assume we've had XmxWinset called on us in redraw_windows. */
  420.  
  421.   /* Set shading model. */
  422.   shademodel (WIN_SHADE(win));
  423.  
  424.   /* Clear window and set backdrop. */
  425.   if (win->backdrop)
  426.     draw_backdrop (win);
  427.   
  428.   if (WIN_FRAME(win) == NULL) 
  429.     {
  430.       /* Assert if FRAME is null but FRAMELIST is not.  Yes,
  431.          that should be == not !=. */
  432.       assert (WIN_FRAMELIST(win) == NULL);
  433.       /* Nothing to draw. */
  434.       swapbuffers();
  435.       return ST_OKAY;
  436.     }
  437.   else 
  438.     {
  439.       obj = FRA_ROOTOBJ(WIN_FRAME(win));
  440.     }
  441.   
  442.   /* Make sure that the object exists, has information associated */
  443.   /* with it, and has a drawing function. */
  444.   assert (obj != NULL);
  445.   assert (obj->info != NULL);
  446.   assert (obj->info->draw_fn != NULL);
  447.   
  448.   /* Save the transformation matrix and the drawing attributes. */
  449.   /* Whatever for?  We don't have anything loaded when we start
  450.      that isn't reloaded every time through. */
  451.   pushmatrix();
  452.   pushviewport();
  453.   pushattributes();
  454.  
  455.   /* Setup transformation matrices. */
  456.   maxwidth = WIN_MAXWIDTH(win);
  457.   height = (float) pv->dv_height;
  458.   width = (float) pv->dv_width;
  459.   if (WIN_PROJECTION(win) == ORTHOGRAPHIC)
  460.     {
  461.       /* Use the spherical viewing distance to determine the scale */
  462.       /* to magnify by. */
  463.       float scl;
  464.       
  465.       /* Calculate the aspect ratio acaling multiplier.  This is */
  466.       /* applied to the x-dimension to adjust for the change in */
  467.       /* aspect ratio of a resizable win. */
  468.       if (width > height) 
  469.         {
  470.           xaspect = height / width;
  471.           yaspect = 1.0;
  472.         }
  473.       else 
  474.         {
  475.           xaspect = 1.0;
  476.           yaspect = width / height;
  477.         }
  478.       
  479.       /* Initialize the transformation matrix --- this has
  480.          to be on the projection stack. */
  481.       mmode (MPROJECTION);
  482.       loadmatrix(ident);
  483.       
  484.       /* Build an orthographic projection matrix and load it. */
  485.       for (i = 0; i < 4; i++)
  486.         for (j = 0; j < 4; j++)
  487.           op[i][j] = 0.0;
  488.       op[0][0] = (2.0 / maxwidth) * xaspect;
  489.       op[1][1] = (2.0 / maxwidth) * yaspect;
  490.       op[2][2] = (-2.0 / maxwidth);
  491.       op[3][3] = 1.0;
  492.       multmatrix(op);
  493.  
  494.       /* Now switch back to the viewing matrix and get that
  495.          set up. */
  496.       mmode (MVIEWING);
  497.       loadmatrix (ident);
  498.       
  499.       scl = maxwidth/(WIN_SFROM(win)[RHO]);
  500.       /* The Z value was 0.95; what for? */
  501.       scale(scl, scl, 1.0);
  502.     }
  503.   else 
  504.     {
  505.       float dist;
  506.       
  507.       dist = fhypot(WIN_CFROM(win)[X]-WIN_STATS(win,PX).mean,
  508.                     fhypot(WIN_CFROM(win)[Y]-
  509.                            WIN_STATS(win,PY).mean,
  510.                            WIN_CFROM(win)[Z]-
  511.                            WIN_STATS(win,PZ).mean));
  512.       
  513.       /* This is new. */
  514.       loadmatrix (ident);
  515.       
  516.       perspective(WIN_FOV(win),
  517.                   ((float)pv->dv_width / (float)pv->dv_height),
  518.                   MAX(maxwidth/200,dist-1.1*maxwidth), dist+1.1*maxwidth);
  519.       
  520.       translate(0.0, 0.0, -WIN_SFROM(win)[RHO]);
  521.     }
  522.   
  523.   /* These have to match equivalent sets of calls in pvdraw.c,
  524.      pvrender.c, pvpick.c, etc etc etc ad nauseum. */
  525.   
  526.   rotate (WIN_TWIST(win), 'z');
  527.  
  528.   rot (90.0-WIN_SFROM(win)[PHI]*180.0/PI,'x');
  529.   rot (-90.0-WIN_SFROM(win)[THETA]*180.0/PI,'y');
  530.   rot (-90.0, 'x');
  531.   
  532.   translate (-WIN_AT(win)[X],-WIN_AT(win)[Y],-WIN_AT(win)[Z]);
  533.   
  534.   /* Get the image root object and recursively draw the object */
  535.   /* structure. */
  536.   status = draw_obj_recurs(state, win, obj, obj->info);
  537.   
  538.   /* Restore the transformation matrix, show the work and return. */
  539.   popattributes();
  540.   popviewport();
  541.   popmatrix();
  542.   
  543.   if (win->legend_flag)
  544.     draw_legend (state, win);
  545.   if (win->credits_flag)
  546.     draw_credits (state, win);
  547.   
  548.   swapbuffers();
  549.   
  550.   return status;
  551. }
  552.  
  553.  
  554.  
  555. /* ----------------------------- draw_legend ------------------------------ */
  556. int draw_legend (state_t *state, window_t *win)
  557. {
  558.   int i;
  559.  
  560.   if (win != NULL)
  561.     {
  562.       zbuffer (FALSE);
  563.       mmode (MSINGLE);
  564.  
  565.       pushmatrix ();
  566.       ortho2 
  567.         (0.0, (float)WIN_WIDTH(win) - 1.0, 0.0, (float)WIN_HEIGHT(win) - 1.0);
  568.       
  569.       /* Now, (0 0) is (left bottom).  We want (left top) = (0 max). */
  570.       
  571.       for (i = 1; i < 255; i++)
  572.         {
  573.           bgnline ();
  574.           PALETTECPACK (i);
  575.           p2i (10+i, WIN_HEIGHT(win) - 10);
  576.           p2i (10+i, WIN_HEIGHT(win) - 10 - 30);
  577.           endline ();
  578.         }
  579.       
  580.       popmatrix ();
  581.       mmode (MVIEWING);
  582.       zbuffer (TRUE);
  583.     }
  584.  
  585.   return ST_OKAY;
  586. }
  587.  
  588.  
  589. /* ----------------------------- draw_credits ----------------------------- */
  590. int draw_credits (state_t *state, window_t *win)
  591. {
  592.   int i;
  593.   char *credits;
  594.  
  595.   if (win != NULL)
  596.     {
  597.       zbuffer (FALSE);
  598.       mmode (MSINGLE);
  599.  
  600.       pushmatrix ();
  601.       ortho2 
  602.         (0.0, (float)WIN_WIDTH(win) - 1.0, 0.0, (float)WIN_HEIGHT(win) - 1.0);
  603.       
  604.       cpack (0xffffff);
  605.       credits = "NCSA Polyview 3.1, 1993";
  606.       cmov2 (WIN_WIDTH(win) - 1 - strwidth(credits), 5);
  607.       charstr (credits);
  608.  
  609.       popmatrix ();
  610.       mmode (MVIEWING);
  611.       zbuffer (TRUE);
  612.     }
  613.  
  614.   return ST_OKAY;
  615. }
  616.  
  617.  
  618.  
  619. /* --------------------------- animate_polyview --------------------------- */
  620. int animate_polyview(state_t *state, window_t *win)
  621. {
  622.   int i;
  623.  
  624.   if (WIN_FORWARD(win) != 0) 
  625.     for (i = WIN_SKIP(win); i >= 0; i--) 
  626.       {
  627.         if (WIN_FRAMEID(win) == WIN_FRAMES(win))
  628.           {
  629.             if (win->bounce)
  630.               {
  631.                 WIN_REVERSE(win) = WIN_FORWARD(win);
  632.                 WIN_FORWARD(win) = 0;
  633.                 WIN_FRAMEID(win)--;
  634.                 WIN_FRAME(win) = get_prev_frame(state, WIN_FRAME(win));
  635.                 goto done;
  636.               }
  637.             else
  638.               WIN_FRAMEID(win) = 1;
  639.           }
  640.         else
  641.           WIN_FRAMEID(win)++;
  642.  
  643.         WIN_FRAME(win) = get_next_frame(state, WIN_FRAME(win));
  644.       }
  645.   
  646.   if (WIN_REVERSE(win) != 0) 
  647.     for (i = WIN_SKIP(win); i >= 0; i--) 
  648.       {
  649.         if (WIN_FRAMEID(win) == 1)
  650.           {
  651.             if (win->bounce)
  652.               {
  653.                 WIN_FORWARD(win) = WIN_REVERSE(win);
  654.                 WIN_REVERSE(win) = 0;
  655.                 WIN_FRAMEID(win)++;
  656.                 WIN_FRAME(win) = get_next_frame(state, WIN_FRAME(win));
  657.                 goto done;
  658.               }
  659.             else
  660.               WIN_FRAMEID(win) = WIN_FRAMES(win);
  661.           }
  662.         else
  663.           WIN_FRAMEID(win)--;
  664.  
  665.         WIN_FRAME(win) = get_prev_frame(state, WIN_FRAME(win));
  666.       }
  667.  
  668.  done:
  669.   set_redraw(state, win);
  670.   send_msg_to_type(state, win, DIALOG, MSG_NEWFRAME);
  671.   
  672.   return ST_OKAY;
  673. }
  674.  
  675. /* ---------------------------- event_polyview ---------------------------- */
  676. int event_polyview(state_t *state, window_t *win, long dev_id, short data)
  677. {
  678.   return ST_OKAY;
  679. }
  680.  
  681.  
  682.  
  683. /* --------------------------- notify_polyview ---------------------------- */
  684. int notify_polyview(state_t *state, window_t *send_win, window_t *recv_win,
  685.                     int message, va_list args)
  686. {
  687.   int status;
  688.   window_t *win;
  689.     
  690.   status = ST_OKAY;
  691.   
  692.   switch (message) 
  693.     {
  694.     case MSG_NEWACT:
  695.       win = va_arg(args, window_t *);
  696.       /* If this is the new active window, set the state to */
  697.       /* reflect that fact, and draw the border. */
  698.       if (send_win  == recv_win) 
  699.         state->active_windows = recv_win;
  700.       else if (recv_win == win) 
  701.         {
  702.           /* Do nothing anymore. */
  703.         }
  704.       break;
  705.     case MSG_NEWFRAME:
  706.     case MSG_NEWDATA:
  707.     case MSG_NEWPICK:
  708.       set_redraw(state, recv_win);
  709.       break;
  710.     case MSG_VIEWCHG:
  711.     case MSG_CLOSING:
  712.       /* When the active window closes, there is no active */
  713.       /* window.  The global active_windows list must be */
  714.       /* cleared. */
  715.       if (send_win == recv_win)
  716.         state->active_windows = NULL;
  717.       break;
  718.     default:
  719.       break;
  720.     }
  721.   
  722.   return status;
  723. }
  724.  
  725.  
  726.  
  727.  
  728. /* ----------------------------- delete_poly ------------------------------ */
  729. /* delete_poly removes associated frames and objects from a window and its */
  730. /* polyview record and then frees the polyview record space, setting the */
  731. /* pointer to NULL.  Returns ST_OKAY if no errors occur. */
  732. /* NEVER CALLED */
  733. static int delete_poly (state_t *state, window_t *win)
  734. {
  735.   frame_t *frame;
  736.   
  737.   /* Keep deleting frames until there are none left. */
  738.   frame = WIN_FRAMELIST(win);
  739.   while (frame != NULL)
  740.     frame = delete_frame (state, win, frame);
  741.   
  742.   /* Free the space associated with the polyview win. */
  743.   PVFREE(win->image);
  744.   
  745.   return ST_OKAY;
  746. }
  747.  
  748. /* --------------------------- destroy_polyview --------------------------- */
  749. int destroy_polyview(state_t *state, window_t *win)
  750. {
  751.   /* This has to shut down the dialog... */
  752.   XtUnmanageChild (win->base);
  753.   XtDestroyWidget (win->base);
  754.   delete_poly(state, win);
  755.   if (WIN_ROOTOBJINFO(win) != NULL)
  756.     delete_objinfo(state, WIN_ROOTOBJINFO(win));
  757.   win->base = NULL;
  758.  
  759.   return ST_OKAY;
  760. }
  761.  
  762.  
  763. /* ----------------------------- create_poly ------------------------------ */
  764. /* create poly creates and initializes a polyview record with default values */
  765. /* Returns a pointer to the initialized structure, NULL if an error occurs. */
  766. static polyview_t * create_poly(state_t *state)
  767. {
  768.   polyview_t        *pv;
  769.   
  770.   /* Create the polyview record. */
  771.   pv = (polyview_t *) PVMALLOC(sizeof(polyview_t));
  772.   
  773.   /* Clear all fields initially. */
  774.   pv->probe = NULL;
  775.   pv->active_window_thread = NULL;
  776.   pv->menubar = NULL;
  777.   pv->active = NULL;
  778.   pv->dtmlockout = NULL;
  779.   pv->blast = NULL; 
  780.   pv->drawing_volume = NULL;
  781.   pv->current_select_token = pv->dv_height = pv->dv_width = 0;
  782.   pv->loadVsetBox = NULL;
  783.   pv->outlineBox = NULL;
  784.   pv->linewidthBox = NULL;
  785.   pv->sphereBox = NULL;
  786.   pv->ray_box = NULL;
  787.   pv->rgb_box = NULL;
  788. #ifdef RENDERMAN
  789.   pv->rm_box = NULL;
  790. #endif
  791.   pv->hdf_box = NULL;
  792.  
  793.   return pv;
  794. }
  795.  
  796.  
  797.  
  798. /* ------------------------------- add_poly ------------------------------- */
  799. /* add_poly creates and initializes a polyview record and adds it to the */
  800. /* specified window.  Returns a pointer to the new record, NULL if an error */
  801. /* occurs. */
  802. /* CALLED FROM win_open_polyview */
  803. polyview_t *add_poly (state_t *state, window_t *win)
  804. {
  805.   polyview_t *polyview;
  806.     
  807.   /* Create a new polyview record. */
  808.   polyview = create_poly(state);
  809.   
  810.   /* Add the record to the win. */
  811.   WIN_IMAGE(win) = (void *)polyview;
  812.   
  813.   return polyview;
  814. }
  815.  
  816.  
  817. /* ------------------------------------------------------------------------ */
  818. /* --------------------------- POLYVIEW WINDOW ---------------------------- */
  819. /* -------------------------- GUI FUNCTIONALITY --------------------------- */
  820. /* ------------------------------------------------------------------------ */
  821.  
  822. void GUIpviewResetRender (state_t *state, window_t *win)
  823. {
  824.   /* For the given polyview window, we reset the gizmos in the
  825.      menubar and elsewhere to match render attributes. */
  826.   polyview_t *pv;
  827.  
  828.   assert (win != NULL);
  829.   assert (win->type == POLYVIEW);
  830.   
  831.   pv = (polyview_t *)WIN_IMAGE(win);
  832.  
  833.   /* Draw mode. */
  834.   XmxRSetToggleState (pv->menubar, PV_PVIEW_DRAW_VERTICES, 
  835.                       (WIN_DRAW(win) == draw_vertices));
  836.   XmxRSetToggleState (pv->menubar, PV_PVIEW_DRAW_EDGES, 
  837.                       (WIN_DRAW(win) == draw_edges));
  838.   XmxRSetToggleState (pv->menubar, PV_PVIEW_DRAW_HIDDEN, 
  839.                       (WIN_DRAW(win) == draw_hidden_edges));
  840.   XmxRSetToggleState (pv->menubar, PV_PVIEW_DRAW_FACES, 
  841.                       (WIN_DRAW(win) == draw_faces));
  842.   XmxRSetToggleState (pv->menubar, PV_PVIEW_DRAW_OUTFACES, 
  843.                       (WIN_DRAW(win) == draw_outlined_faces));
  844.   
  845.   /* Drag mode. */
  846.   XmxRSetToggleState (pv->menubar, PV_PVIEW_DRAG_NOTHING,
  847.                       (win->fastdraw_fn == draw_nothing));
  848.   XmxRSetToggleState (pv->menubar, PV_PVIEW_DRAG_BOX,
  849.                       (win->fastdraw_fn == draw_box));
  850.   XmxRSetToggleState (pv->menubar, PV_PVIEW_DRAG_VERTICES,
  851.                       (win->fastdraw_fn == draw_vertices));
  852.   XmxRSetToggleState (pv->menubar, PV_PVIEW_DRAG_EDGES,
  853.                       (win->fastdraw_fn == draw_edges));
  854.   XmxRSetToggleState (pv->menubar, PV_PVIEW_DRAG_HIDDEN,
  855.                       (win->fastdraw_fn == draw_hidden_edges));
  856.   XmxRSetToggleState (pv->menubar, PV_PVIEW_DRAG_FACES,
  857.                       (win->fastdraw_fn == draw_faces));
  858.   XmxRSetToggleState (pv->menubar, PV_PVIEW_DRAG_OUTFACES,
  859.                       (win->fastdraw_fn == draw_outlined_faces));
  860.   XmxRSetToggleState (pv->menubar, PV_PVIEW_DRAG_SAMEASDRAW,
  861.                       (win->fastdraw_fn == NULL));
  862.  
  863.   /* Projection mode. */
  864.   XmxRSetToggleState (pv->menubar, PV_PVIEW_PROJ_PERSPECTIVE,
  865.                       (WIN_PROJECTION(win) == PERSPECTIVE));
  866.   XmxRSetToggleState (pv->menubar, PV_PVIEW_PROJ_ORTHOGRAPHIC,
  867.                       (WIN_PROJECTION(win) == ORTHOGRAPHIC));
  868.   
  869.   /* Shade mode. */
  870.   XmxRSetToggleState (pv->menubar, PV_PVIEW_SHADE_GOURAUD,
  871.                       (WIN_SHADE(win) == GOURAUD));
  872.   XmxRSetToggleState (pv->menubar, PV_PVIEW_SHADE_FLAT,
  873.                       (WIN_SHADE(win) == FLAT));
  874.  
  875.   /* Lights. */
  876.   XmxRSetToggleState (pv->menubar, PV_PVIEW_LIGHT_ONE,
  877.                       (WIN_LIGHT(win) && FEQ(WIN_LIGHT_X(win), 0.5)));
  878.   XmxRSetToggleState (pv->menubar, PV_PVIEW_LIGHT_TWO,
  879.                       (WIN_LIGHT(win) && FEQ(WIN_LIGHT_X(win), -0.5)));
  880.   XmxRSetToggleState (pv->menubar, PV_PVIEW_LIGHT_THREE,
  881.                       (WIN_LIGHT(win) && FEQ(WIN_LIGHT_X(win), 0.707)));
  882.   XmxRSetToggleState (pv->menubar, PV_PVIEW_LIGHT_X,
  883.                       (WIN_LIGHT(win) && FEQ(WIN_LIGHT_X(win), 1.0) && 
  884.                        FEQ(WIN_LIGHT_Y(win), 0.0)));
  885.   XmxRSetToggleState (pv->menubar, PV_PVIEW_LIGHT_Y,
  886.                       (WIN_LIGHT(win) && FEQ(WIN_LIGHT_Y(win), 1.0) && 
  887.                        FEQ(WIN_LIGHT_X(win), 0.0)));
  888.   XmxRSetToggleState (pv->menubar, PV_PVIEW_LIGHT_Z,
  889.                       (WIN_LIGHT(win) && FEQ(WIN_LIGHT_Z(win), 1.0) && 
  890.                        FEQ(WIN_LIGHT_Y(win), 0.0)));
  891.   XmxRSetToggleState (pv->menubar, PV_PVIEW_LIGHT_OFF, (!WIN_LIGHT(win)));
  892.   XmxRSetToggleState (pv->menubar, PV_PVIEW_LIGHT_TWOSIDE,
  893.                       WIN_LIGHT_TWOSIDE(win));
  894.   
  895.   /* Also do dialog adjustments as appropriate. */
  896.   return;
  897. }
  898.  
  899.  
  900.  
  901. /* -------------------------- GUIpviewResetProps -------------------------- */
  902. void GUIpviewResetProps (state_t *state, window_t *win)
  903. {
  904.   /* For the given polyview window, we reset the gizmos in the
  905.      menubar and elsewhere to match props attributes. */
  906.   polyview_t *pv;
  907.   int value, value2;
  908.   
  909.   assert (win != NULL);
  910.   assert (win->type == POLYVIEW);
  911.   
  912.   pv = (polyview_t *)WIN_IMAGE(win);
  913.   value = WIN_ROOTOBJINFO(win)->hereonly.value;
  914.   value2 = WIN_ROOTOBJINFO(win)->heredown.value;
  915.  
  916.   XmxRSetToggleState (pv->menubar, PV_PROPS_AXES_LARGE,
  917.                       value & AXESLARGE ? 1 : 0);
  918.   XmxRSetToggleState (pv->menubar, PV_PROPS_AXES_SMALL,
  919.                       value & AXESSMALL ? 1 : 0);
  920.   XmxRSetToggleState (pv->menubar, PV_PROPS_AXES_OFF,
  921.                       !(value & AXESSMALL) && !(value & AXESLARGE) ? 1 : 0);
  922.   
  923.   XmxRSetToggleState (pv->menubar, PV_PROPS_BOX_EDGESFACES,
  924.                       (value & BOXWIRE) && (value & BOXSHADED) ? 1 : 0);
  925.   XmxRSetToggleState (pv->menubar, PV_PROPS_BOX_FACES,
  926.                       (value & BOXSHADED) && !(value & BOXWIRE) ? 1 : 0);
  927.   XmxRSetToggleState (pv->menubar, PV_PROPS_BOX_EDGES,
  928.                       (value & BOXWIRE) && !(value & BOXSHADED) ? 1 : 0);
  929.   XmxRSetToggleState (pv->menubar, PV_PROPS_BOX_OFF,
  930.                       !(value & BOXWIRE) && !(value & BOXSHADED) ? 1 : 0);
  931.  
  932.   XmxRSetToggleState (pv->menubar, PV_PROPS_GRID_XY,
  933.                       (value & GRIDXY) ? 1 : 0);
  934.   XmxRSetToggleState (pv->menubar, PV_PROPS_GRID_YZ,
  935.                       (value & GRIDYZ) ? 1 : 0);
  936.   XmxRSetToggleState (pv->menubar, PV_PROPS_GRID_XZ,
  937.                       (value & GRIDXZ) ? 1 : 0);
  938.  
  939.   XmxRSetToggleState (pv->menubar, PV_PROPS_SHADOW_XY,
  940.                       (value2 & SCATXY) ? 1 : 0);
  941.   XmxRSetToggleState (pv->menubar, PV_PROPS_SHADOW_YZ,
  942.                       (value2 & SCATYZ) ? 1 : 0);
  943.   XmxRSetToggleState (pv->menubar, PV_PROPS_SHADOW_XZ,
  944.                       (value2 & SCATXZ) ? 1 : 0);
  945.  
  946.   XmxRSetToggleState (pv->menubar, PV_PROPS_LEGEND,
  947.                       win->legend_flag);
  948.   XmxRSetToggleState (pv->menubar, PV_PROPS_CREDITS,
  949.                       win->credits_flag);
  950.  
  951.    /* Also do dialog adjustments as appropriate. */
  952.   return;
  953. }
  954.  
  955.  
  956.  
  957. /* ------------------------- GUIpviewResetOutline ------------------------- */
  958. void GUIpviewResetOutline (state_t *state, window_t *win)
  959. {
  960.   polyview_t *pv;
  961.   int val;
  962.  
  963.   pv = (polyview_t *)WIN_IMAGE(win);
  964.  
  965.   /* Punt if the dialog box hasn't been created yet. */
  966.   if (pv->outlineBox == NULL)
  967.     return;
  968.  
  969.   val = (int)((float)(WIN_OUTLINE_COLOR(win) & 0x000000ff) / 2.55);
  970.   /* Don't ask me... */
  971.   if (val > 0 || val < 100)
  972.     val++;
  973.  
  974.   PVD (("Adjusting outlinebox scale.\n"));
  975.   XmxAdjustScale 
  976.     (pv->outlineBox->color_scale, val);
  977.   PVD (("Done with outline.\n"));
  978.   
  979.   return;
  980. }
  981.  
  982.  
  983. /* ------------------------ GUIpviewResetLinewidth ------------------------ */
  984. void GUIpviewResetLinewidth (state_t *state, window_t *win)
  985. {
  986.   polyview_t *pv;
  987.   int val;
  988.  
  989.   pv = (polyview_t *)WIN_IMAGE(win);
  990.  
  991.   /* Punt if the dialog box hasn't been created yet. */
  992.   if (pv->linewidthBox == NULL)
  993.     return;
  994.  
  995.   PVD (("Adjusting linewidthbox scale.\n"));
  996.   XmxAdjustScale 
  997.     (pv->linewidthBox->width_scale, win->line_width);
  998.   PVD (("Done with linewidth.\n"));
  999.   
  1000.   return;
  1001. }
  1002.  
  1003. /* ------------------------- GUIpviewResetSelect -------------------------- */
  1004. void GUIpviewResetSelect (state_t *state, window_t *win)
  1005. {
  1006.   /* For the given polyview window, we reset the gizmos in the
  1007.      menubar and elsewhere to match pick/select attributes. */
  1008.   polyview_t *pv;
  1009.   
  1010.   assert (win != NULL);
  1011.   assert (win->type == POLYVIEW);
  1012.   
  1013.   pv = (polyview_t *)WIN_IMAGE(win);
  1014.  
  1015.   XmxRSetToggleState (pv->menubar, PV_PVIEW_SELECT_VERTICES,
  1016.                       win->pickmode == PICK_VERTEX);
  1017.   XmxRSetToggleState (pv->menubar, PV_PVIEW_SELECT_FACES,
  1018.                       win->pickmode == PICK_FACE);
  1019.   XmxRSetToggleState (pv->menubar, PV_PVIEW_SELECT_OBJECTS,
  1020.                       win->pickmode == PICK_OBJECT);
  1021.  
  1022.   return;
  1023. }
  1024.  
  1025.  
  1026.  
  1027. /* ------------------------------------------------------------------------ */
  1028. /* ---------------------------- LOAD VSET BOX ----------------------------- */
  1029. /* ------------------------------------------------------------------------ */
  1030.  
  1031. /* ------------------------- GUIloadVsetCallback -------------------------- */
  1032. XmxCallback (GUIloadVsetCallback)
  1033. {
  1034.   window_t *win;
  1035.   polyview_t *pv;
  1036.   char line[MAXLINELEN];
  1037.   GUIloadVsetBox *box;
  1038.   char *fname;
  1039.  
  1040.   /* Go get the window from the state's window list. */
  1041.   win = find_window_by_id (gstate, XmxExtractUniqid ((int)client_data));
  1042.   assert (win != NULL);
  1043.   
  1044.   /* Make the window active; this won't put an 'activate window'
  1045.      message in the history list, which is how Polyview 2.0 works. */
  1046.   if (win != gstate->active_windows)
  1047.     win_activate (gstate, win);
  1048.   
  1049.   pv = (polyview_t *)WIN_IMAGE(win);
  1050.   box = pv->loadVsetBox;
  1051.   
  1052.   /* Get rid of the dialog first. */
  1053.   XtUnmanageChild (w);
  1054.  
  1055.   /* First do axes and color/connect.  We do these by hand, and install
  1056.      commands in the history list to fake the results. */
  1057.   strcpy (win->vname[PX], XmxTextGetString (box->x_text));
  1058.   sprintf (line, "data x-axis %s\0", XmxTextGetString (box->x_text));
  1059.   GUIaddCommand (line);
  1060.   TRANSaddCommand(gstate, line);
  1061.  
  1062.   strcpy (win->vname[PY], XmxTextGetString (box->y_text));
  1063.   sprintf (line, "data y-axis %s\0", XmxTextGetString (box->y_text));
  1064.   GUIaddCommand (line);
  1065.   TRANSaddCommand(gstate, line);
  1066.  
  1067.   strcpy (win->vname[PZ], XmxTextGetString (box->z_text));
  1068.   sprintf (line, "data z-axis %s\0", XmxTextGetString (box->z_text));
  1069.   GUIaddCommand (line);
  1070.   TRANSaddCommand(gstate, line);
  1071.  
  1072.   strcpy (win->vname[MCONNECT], XmxTextGetString (box->connect_text));
  1073.   sprintf (line, "data connect %s\0", XmxTextGetString (box->connect_text));
  1074.   GUIaddCommand (line);
  1075.   TRANSaddCommand(gstate, line);
  1076.  
  1077.   strcpy (win->vname[MVSCALAR], XmxTextGetString (box->color_text));
  1078.   sprintf (line, "data color %s\0", XmxTextGetString (box->color_text));
  1079.   GUIaddCommand (line);
  1080.   TRANSaddCommand(gstate, line);
  1081.  
  1082.   /* Grab the filename. */
  1083.   fname = (char *)PVMALLOC (128 * sizeof (char));
  1084.   XmStringGetLtoR 
  1085.     (((XmFileSelectionBoxCallbackStruct *)call_data)->value,
  1086.      XmSTRING_DEFAULT_CHARSET, &fname);
  1087.   
  1088.   /* Open the file. */
  1089.   if ((WIN_SOURCE(win) = find_file (gstate, HDFVSET, fname)) == NULL)
  1090.     {
  1091.       /* Error - open dialog box. */
  1092.       sprintf (line, "File '%s' could not be opened.", fname);
  1093.       XmxMakeErrorDialog (w, line, "Error While Loading Vset");
  1094.       XtManageChild (Xmx_w);
  1095.       goto done;
  1096.     }
  1097.  
  1098.   /* The file is open; fake the history list. */
  1099.   sprintf (line, "data file %s\0", fname);
  1100.   GUIaddCommand (line);
  1101.   TRANSaddCommand(gstate, line);
  1102.  
  1103.   /* Also rename the window here, both win->name and the dialog
  1104.      title. */
  1105.   /* This may end up being a problem, since this name change
  1106.      will not be reflected in the transcript. */
  1107.   strcpy (win->name, fname);
  1108.   sprintf (line, "Polyview 3.1: %s", fname);
  1109.   XmxAdjustDialogTitle (win->base, line);
  1110.  
  1111.   /* Call data_frame. */
  1112.   if (data_frame (gstate, win, XmxTextGetString (box->frame_text)) == ST_ERROR)
  1113.     {
  1114.       /* Error - open dialog box. */
  1115.       sprintf (line, "Could not find Vgroup(s) named '%s' in this Vset..", 
  1116.                XmxTextGetString (box->frame_text));
  1117.       XmxMakeErrorDialog (w, line, "Error While Loading Vset");
  1118.       XtManageChild (Xmx_w);
  1119.       goto done;
  1120.     }
  1121.  
  1122.   /* data_frame was successful; fake the history list. */
  1123.   sprintf (line, "data frame %s\0", XmxTextGetString (box->frame_text));
  1124.   GUIaddCommand (line);
  1125.   TRANSaddCommand(gstate, line);
  1126.  
  1127.   /* If we've gotten this far, might as well load the data...? */
  1128.   parse_line (gstate, "data load", TRUE);
  1129.  
  1130.  done:
  1131.   free (fname);
  1132.   return;
  1133. }
  1134.  
  1135.  
  1136.  
  1137. /* ------------------------- GUIcreateLoadVsetBox ------------------------- */
  1138. GUIloadVsetBox *GUIcreateLoadVsetBox (state_t *state, window_t *win)
  1139. {
  1140.   GUIloadVsetBox *box;
  1141.   Widget frame;
  1142.   Widget x_label, y_label, z_label;
  1143.   Widget connect_label, color_label, frame_label;
  1144.   Widget sep1;
  1145.  
  1146.   box = (GUIloadVsetBox *)PVMALLOC (sizeof (GUIloadVsetBox));
  1147.  
  1148.   /* Set uniqid for dialog box. */
  1149.   XmxSetUniqid (win->id);
  1150.  
  1151.   box->base = XmxMakeFileSBDialog
  1152.     (win->base, "Load Vset", "Enter name of HDF Vset file:",
  1153.      GUIloadVsetCallback, 0);
  1154.  
  1155.   /* This makes a form as a work area for the dialog box. */
  1156.   XmxSetArg (XmNmarginWidth, 5);
  1157.   XmxSetArg (XmNmarginHeight, 5);
  1158.   frame = XmxMakeFrame (box->base, XmxShadowEtchedIn);
  1159.  
  1160.   box->workarea = XmxMakeForm (frame);
  1161.  
  1162.   x_label = XmxMakeLabel (box->workarea, "X Axis Vdata name:");
  1163.   XmxSetArg (XmNwidth, 210);
  1164.   box->x_text = XmxMakeText (box->workarea);
  1165.   XmxTextSetString (box->x_text, DEF_PXNAME);
  1166.  
  1167.   y_label = XmxMakeLabel (box->workarea, "Y Axis Vdata name:");
  1168.   XmxSetArg (XmNwidth, 210);
  1169.   box->y_text = XmxMakeText (box->workarea);
  1170.   XmxTextSetString (box->y_text, DEF_PYNAME);
  1171.  
  1172.   z_label = XmxMakeLabel (box->workarea, "Z Axis Vdata name:");
  1173.   XmxSetArg (XmNwidth, 210);
  1174.   box->z_text = XmxMakeText (box->workarea);
  1175.   XmxTextSetString (box->z_text, DEF_PZNAME);
  1176.  
  1177.   connect_label = XmxMakeLabel (box->workarea, "Connectivity Vdata name:");
  1178.   XmxSetArg (XmNwidth, 210);
  1179.   box->connect_text = XmxMakeText (box->workarea);
  1180.   XmxTextSetString (box->connect_text, DEF_CONNECTNAME);
  1181.  
  1182.   color_label = XmxMakeLabel (box->workarea, "Color Vdata name:");
  1183.   XmxSetArg (XmNwidth, 210);
  1184.   box->color_text = XmxMakeText (box->workarea);
  1185.   XmxTextSetString (box->color_text, DEF_VSCALARNAME);
  1186.  
  1187.   sep1 = XmxMakeHorizontalSeparator (box->workarea);
  1188.  
  1189.   frame_label = XmxMakeLabel (box->workarea, "Frames to load:");
  1190.   XmxSetArg (XmNwidth, 210);
  1191.   box->frame_text = XmxMakeText (box->workarea);
  1192.   XmxTextSetString (box->frame_text, DEF_GROUPNAME);
  1193.  
  1194.   /* Constraints for box->workarea. */
  1195.   XmxSetConstraints 
  1196.     (x_label, XmATTACH_FORM, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_NONE,
  1197.      NULL, NULL, NULL, NULL);
  1198.   XmxSetConstraints
  1199.     (box->x_text, XmATTACH_FORM, XmATTACH_NONE, XmATTACH_NONE, XmATTACH_FORM,
  1200.      NULL, NULL, NULL, NULL);
  1201.   XmxSetConstraints
  1202.     (y_label, XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_NONE,
  1203.      box->x_text, NULL, NULL, NULL);
  1204.   XmxSetConstraints
  1205.     (box->y_text, XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_NONE, XmATTACH_FORM,
  1206.      box->x_text, NULL, NULL, NULL);
  1207.   XmxSetConstraints
  1208.     (z_label, XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_NONE,
  1209.      box->y_text, NULL, NULL, NULL);
  1210.   XmxSetConstraints
  1211.     (box->z_text, XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_NONE, XmATTACH_FORM,
  1212.      box->y_text, NULL, NULL, NULL);
  1213.   XmxSetConstraints
  1214.     (connect_label, XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_FORM, 
  1215.      XmATTACH_NONE, box->z_text, NULL, NULL, NULL);
  1216.   XmxSetConstraints
  1217.     (box->connect_text, XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_NONE, 
  1218.      XmATTACH_FORM, box->z_text, NULL, NULL, NULL);
  1219.   XmxSetConstraints
  1220.     (color_label, XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_FORM, 
  1221.      XmATTACH_NONE, box->connect_text, NULL, NULL, NULL);
  1222.   XmxSetConstraints
  1223.     (box->color_text, XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_NONE, 
  1224.      XmATTACH_FORM, box->connect_text, NULL, NULL, NULL);
  1225.   XmxSetConstraints
  1226.     (sep1, XmATTACH_WIDGET, XmATTACH_WIDGET, XmATTACH_FORM, XmATTACH_FORM,
  1227.      box->color_text, box->frame_text, NULL, NULL);
  1228.   XmxSetConstraints
  1229.     (frame_label, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_FORM, XmATTACH_NONE,
  1230.      NULL, NULL, NULL, NULL);
  1231.   XmxSetConstraints
  1232.     (box->frame_text, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_NONE, 
  1233.      XmATTACH_FORM, NULL, NULL, NULL, NULL);
  1234.   
  1235.   XmxZeroUniqid ();
  1236.  
  1237.   /* Dialog will be managed in the calling routine. */
  1238.   return box;
  1239. }
  1240.  
  1241.  
  1242.  
  1243.  
  1244. /* ------------------------------------------------------------------------ */
  1245. /* -------------------------- OUTLINE COLOR BOX --------------------------- */
  1246. /* ------------------------------------------------------------------------ */
  1247.  
  1248. static XmxCallback (GUIcolorScaleCB)
  1249. {
  1250.   window_t *win;
  1251.   char line[MAXLINELEN];
  1252.   int val = ((XmScaleCallbackStruct *)call_data)->value, c;
  1253.   float col;
  1254.  
  1255.   /* Go get the window from the state's window list. */
  1256.   win = find_window_by_id (gstate, XmxExtractUniqid ((int)client_data));
  1257.   assert (win != NULL);
  1258.   
  1259.   if (WIN_DRAW(win) != draw_outlined_faces)
  1260.     {
  1261.       /* We're not drawing outlined faces yet, so let someone
  1262.          else do the work. */
  1263.       sprintf (line, "draw outlined %f", (float)val * 0.01);
  1264.       parse_line (gstate, line, TRUE);
  1265.     }
  1266.   else
  1267.     {
  1268.       /* We are drawing outlined faces already, so do it fast. */
  1269.       c = (int)((float)val * 2.55);
  1270.       if (c != (WIN_OUTLINE_COLOR(win) & 0x000000ff))
  1271.         {
  1272.           PLAYAFILE ("/usr/lib/sounds/prosonus/instr/woodblock.aiff");
  1273.           WIN_OUTLINE_COLOR(win) = c + (c << 8) + (c << 16);
  1274.           set_redraw (gstate, win);
  1275.           
  1276.           sprintf (line, "draw outlined %0.2f", (float)val * 0.01);
  1277.           GUIaddCommand (line);
  1278.       TRANSaddCommand(gstate, line);
  1279.         }
  1280.     }
  1281.  
  1282.   return;
  1283. }
  1284.  
  1285.  
  1286. static XmxCallback (GUIcolorOKButtonCB)
  1287. {
  1288.   window_t *win;
  1289.   polyview_t *pv;
  1290.  
  1291.   /* Go get the window from the state's window list. */
  1292.   win = find_window_by_id (gstate, XmxExtractUniqid ((int)client_data));
  1293.   assert (win != NULL);
  1294.   
  1295.   pv = (polyview_t *)WIN_IMAGE(win);
  1296.   XtUnmanageChild (pv->outlineBox->base);
  1297.   
  1298.   return;
  1299. }
  1300.  
  1301. GUIoutlineBox *GUIcreateOutlineBox (state_t *state, window_t *win)
  1302. {
  1303.   GUIoutlineBox *box;
  1304.   Widget dialog_frame, control_form, color_label;
  1305.   Widget dialog_sep, buttons_form;
  1306.  
  1307.   box = (GUIoutlineBox *)PVMALLOC (sizeof (GUIoutlineBox));
  1308.  
  1309.   /* Dialog will have same uniqid as polyview window. */
  1310.   XmxSetUniqid (win->id);
  1311.  
  1312.   /* Set up dialog. */
  1313.   box->base = XmxMakeFormDialog (win->base, "Outline Color");
  1314.   dialog_frame = XmxMakeFrame (box->base, XmxShadowOut);
  1315.   XmxSetConstraints 
  1316.     (dialog_frame, XmATTACH_FORM, XmATTACH_FORM, XmATTACH_FORM, XmATTACH_FORM,
  1317.      NULL, NULL, NULL, NULL);
  1318.  
  1319.   /* Main control form. */
  1320.   XmxSetArg (XmNhorizontalSpacing, 10);
  1321.   control_form = XmxMakeForm (dialog_frame);
  1322.  
  1323.   /* Label and slider. */
  1324.   color_label = XmxMakeLabel (control_form, "Outline Color:");
  1325.   XmxSetArg (XmNwidth, 250);
  1326.   box->color_scale = XmxMakeScale
  1327.     (control_form, GUIcolorScaleCB, 0, NULL, 0, 100,
  1328.      (int) (((float)win->outline_color / (float)0xffffff) * 100.0), 2);
  1329.  
  1330.   /* Separator and buttons for dialog box. */
  1331.   dialog_sep = XmxMakeHorizontalSeparator (control_form);
  1332.   buttons_form = XmxMakeFormAndOneButton
  1333.     (control_form, GUIcolorOKButtonCB, "OK", 0);
  1334.   
  1335.   /* Constraints for control_form. */
  1336.   XmxSetArg (XmNtopOffset, 10);
  1337.   XmxSetConstraints 
  1338.     (color_label, XmATTACH_FORM, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_NONE,
  1339.      NULL, NULL, NULL, NULL);
  1340.   XmxSetArg (XmNbottomOffset, 10);
  1341.   XmxSetConstraints
  1342.     (box->color_scale, XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_FORM,
  1343.      XmATTACH_FORM, color_label, NULL, NULL, NULL);
  1344.   XmxSetArg (XmNtopOffset, 10);
  1345.   XmxSetConstraints
  1346.     (dialog_sep, XmATTACH_WIDGET, XmATTACH_WIDGET, XmATTACH_FORM,
  1347.      XmATTACH_FORM, box->color_scale, buttons_form, NULL, NULL);
  1348.   XmxSetConstraints
  1349.     (buttons_form, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_FORM, XmATTACH_FORM,
  1350.      NULL, NULL, NULL, NULL);
  1351.  
  1352.   return box;
  1353. }
  1354.  
  1355.  
  1356.  
  1357. /* ------------------------------------------------------------------------ */
  1358. /* ---------------------------- LINEWIDTH BOX ----------------------------- */
  1359. /* ------------------------------------------------------------------------ */
  1360.  
  1361. static XmxCallback (GUIwidthScaleCB)
  1362. {
  1363.   window_t *win;
  1364.   char line[MAXLINELEN];
  1365.   int val = ((XmScaleCallbackStruct *)call_data)->value;
  1366.  
  1367.   /* Go get the window from the state's window list. */
  1368.   win = find_window_by_id (gstate, XmxExtractUniqid ((int)client_data));
  1369.   assert (win != NULL);
  1370.   
  1371.   if (val != win->line_width)
  1372.     {
  1373.       PLAYAFILE ("/usr/lib/sounds/prosonus/instr/woodblock.aiff");
  1374.       win->line_width = val;
  1375.       set_redraw (gstate, win);
  1376.       
  1377.       sprintf (line, "draw linewidth %d", val);
  1378.       GUIaddCommand (line);
  1379.       TRANSaddCommand(gstate, line);
  1380.  
  1381.     }
  1382.   
  1383.   return;
  1384. }
  1385.  
  1386.  
  1387. static XmxCallback (GUIwidthOKButtonCB)
  1388. {
  1389.   window_t *win;
  1390.   polyview_t *pv;
  1391.  
  1392.   /* Go get the window from the state's window list. */
  1393.   win = find_window_by_id (gstate, XmxExtractUniqid ((int)client_data));
  1394.   assert (win != NULL);
  1395.   
  1396.   pv = (polyview_t *)WIN_IMAGE(win);
  1397.   XtUnmanageChild (pv->linewidthBox->base);
  1398.   
  1399.   return;
  1400. }
  1401.  
  1402.  
  1403.  
  1404. GUIlinewidthBox *GUIcreateLinewidthBox (state_t *state, window_t *win)
  1405. {
  1406.   GUIlinewidthBox *box;
  1407.   Widget dialog_frame, control_form, width_label;
  1408.   Widget dialog_sep, buttons_form;
  1409.  
  1410.   box = (GUIlinewidthBox *)PVMALLOC (sizeof (GUIlinewidthBox));
  1411.  
  1412.   /* Dialog will have same uniqid as polyview window. */
  1413.   XmxSetUniqid (win->id);
  1414.  
  1415.   /* Set up dialog. */
  1416.   box->base = XmxMakeFormDialog (win->base, "Linewidth Control");
  1417.   dialog_frame = XmxMakeFrame (box->base, XmxShadowOut);
  1418.   XmxSetConstraints 
  1419.     (dialog_frame, XmATTACH_FORM, XmATTACH_FORM, XmATTACH_FORM, XmATTACH_FORM,
  1420.      NULL, NULL, NULL, NULL);
  1421.  
  1422.   /* Main control form. */
  1423.   XmxSetArg (XmNhorizontalSpacing, 10);
  1424.   control_form = XmxMakeForm (dialog_frame);
  1425.  
  1426.   /* Label and slider. */
  1427.   width_label = XmxMakeLabel (control_form, "Linewidth:");
  1428.   XmxSetArg (XmNwidth, 250);
  1429.   box->width_scale = XmxMakeScale
  1430.     (control_form, GUIwidthScaleCB, 0, NULL, 1, 10, win->line_width, 0);
  1431.  
  1432.   /* Separator and buttons for dialog box. */
  1433.   dialog_sep = XmxMakeHorizontalSeparator (control_form);
  1434.   buttons_form = XmxMakeFormAndOneButton
  1435.     (control_form, GUIwidthOKButtonCB, "OK", 0);
  1436.   
  1437.   /* Constraints for control_form. */
  1438.   XmxSetArg (XmNtopOffset, 10);
  1439.   XmxSetConstraints 
  1440.     (width_label, XmATTACH_FORM, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_NONE,
  1441.      NULL, NULL, NULL, NULL);
  1442.   XmxSetArg (XmNbottomOffset, 10);
  1443.   XmxSetConstraints
  1444.     (box->width_scale, XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_FORM,
  1445.      XmATTACH_FORM, width_label, NULL, NULL, NULL);
  1446.   XmxSetArg (XmNtopOffset, 10);
  1447.   XmxSetConstraints
  1448.     (dialog_sep, XmATTACH_WIDGET, XmATTACH_WIDGET, XmATTACH_FORM,
  1449.      XmATTACH_FORM, box->width_scale, buttons_form, NULL, NULL);
  1450.   XmxSetConstraints
  1451.     (buttons_form, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_FORM, XmATTACH_FORM,
  1452.      NULL, NULL, NULL, NULL);
  1453.  
  1454.   return box;
  1455. }
  1456.  
  1457.  
  1458.  
  1459.  
  1460. /* ------------------------------------------------------------------------ */
  1461. /* ------------------------------ SPHERE BOX ------------------------------ */
  1462. /* ------------------------------------------------------------------------ */
  1463.  
  1464. static XmxCallback (GUIsphereOKButtonCB)
  1465. {
  1466.   window_t *win;
  1467.   polyview_t *pv;
  1468.   char *value, *sptr;
  1469.   float sphereSize;
  1470.  
  1471.   /* Go get the window from the state's window list. */
  1472.   win = find_window_by_id (gstate, XmxExtractUniqid ((int)client_data));
  1473.   assert (win != NULL);
  1474.   
  1475.   pv = (polyview_t *)WIN_IMAGE(win);
  1476.   XtUnmanageChild (pv->sphereBox->base);
  1477.   value = XmxTextGetString(pv->sphereBox->size_text);
  1478.   sphereSize = (float)strtod(value, &sptr);
  1479.   if (sptr != value &&
  1480.       win->sphere_size != sphereSize) {
  1481.     char line[MAXLINELEN];
  1482.     sprintf (line, "sphere size %f", sphereSize);
  1483.     parse_line (gstate, line, TRUE);
  1484.   }
  1485.   XtFree(value);
  1486.  
  1487.   return;
  1488. }
  1489.  
  1490.  
  1491. void GUIpviewResetSphere (state_t *state, window_t *win)
  1492. {
  1493.   polyview_t *pv;
  1494.   int val;
  1495.   char line[MAXLINELEN];
  1496.  
  1497.   pv = (polyview_t *)WIN_IMAGE(win);
  1498.  
  1499.   /* Punt if the dialog box hasn't been created yet. */
  1500.   if (pv->sphereBox == NULL)
  1501.     return;
  1502.  
  1503.   /* Do yer stuff. */
  1504.   
  1505.   /* Who'd wanna go higher than 10? */
  1506.   if (win->sphere_depth <= 10)
  1507.     XmxAdjustScale (pv->sphereBox->depth_scale, win->sphere_depth);
  1508.   else
  1509.     XmxAdjustScale (pv->sphereBox->depth_scale, 10);
  1510.   
  1511.   sprintf (line, "%1.3f", win->sphere_size);
  1512.   XmxTextSetString (pv->sphereBox->size_text, line);
  1513.  
  1514.   return;
  1515. }
  1516.  
  1517.  
  1518. static XmxCallback (GUIspheredepthScaleCB)
  1519. {
  1520.   window_t *win;
  1521.   char line[MAXLINELEN];
  1522.   int val = ((XmScaleCallbackStruct *)call_data)->value;
  1523.  
  1524.   /* Go get the window from the state's window list. */
  1525.   win = find_window_by_id (gstate, XmxExtractUniqid ((int)client_data));
  1526.   assert (win != NULL);
  1527.  
  1528.   /* Beeeeeeee smart. */
  1529.   if (val != win->sphere_depth)
  1530.     {
  1531.       PLAYAFILE ("/usr/lib/sounds/prosonus/instr/woodblock.aiff");
  1532.       win->sphere_depth = val;
  1533.       set_redraw (gstate, win);
  1534.       
  1535.       sprintf (line, "sphere depth %d", val);
  1536.       GUIaddCommand (line);
  1537.       TRANSaddCommand(gstate, line);
  1538.     }
  1539.   
  1540.   return;
  1541. }
  1542.  
  1543. static XmxCallback (GUIspheresizeTextCB)
  1544. {
  1545.   char line[MAXLINELEN];
  1546.   float val;
  1547.   int rc;
  1548.  
  1549.   rc = sscanf (XmxTextGetString (w), "%f", &val);
  1550.   if (rc == 1)
  1551.     {
  1552.       /* Got our value. */
  1553.       sprintf (line, "sphere size %f", val);
  1554.       parse_line (gstate, line, TRUE);
  1555.     }
  1556.  
  1557.   return;
  1558. }
  1559.  
  1560.  
  1561.  
  1562. GUIsphereBox *GUIcreateSphereBox (state_t *state, window_t *win)
  1563. {
  1564.   GUIsphereBox *box;
  1565.   Widget dialog_frame, control_form, size_label, depth_label;
  1566.   Widget mid_sep;
  1567.   Widget dialog_sep, buttons_form;
  1568.   char line[MAXLINELEN];
  1569.  
  1570.   box = (GUIsphereBox *)PVMALLOC (sizeof (GUIsphereBox));
  1571.  
  1572.   /* Dialog will have same uniqid as polyview window. */
  1573.   XmxSetUniqid (win->id);
  1574.  
  1575.   /* Set up dialog. */
  1576.   box->base = XmxMakeFormDialog (win->base, "Sphere Control");
  1577.   dialog_frame = XmxMakeFrame (box->base, XmxShadowOut);
  1578.   XmxSetConstraints 
  1579.     (dialog_frame, XmATTACH_FORM, XmATTACH_FORM, XmATTACH_FORM, XmATTACH_FORM,
  1580.      NULL, NULL, NULL, NULL);
  1581.  
  1582.   /* Main control form. */
  1583.   XmxSetArg (XmNhorizontalSpacing, 10);
  1584.   control_form = XmxMakeForm (dialog_frame);
  1585.  
  1586.   /* Label and slider. */
  1587.   size_label = XmxMakeLabel (control_form, "Sphere Size:");
  1588.   XmxSetArg (XmNcolumns, 15);
  1589.   box->size_text = XmxMakeText (control_form);
  1590.   XmxAddCallbackToText (box->size_text, GUIspheresizeTextCB, 0);
  1591.   sprintf (line, "%1.3f", win->sphere_size);
  1592.   XmxTextSetString (box->size_text, line);
  1593.  
  1594.   mid_sep = XmxMakeHorizontalSeparator (control_form);
  1595.  
  1596.   depth_label = XmxMakeLabel (control_form, "Sphere Depth:");
  1597.   XmxSetArg (XmNwidth, 250);
  1598.   box->depth_scale = XmxMakeScale
  1599.     (control_form, GUIspheredepthScaleCB, 0, NULL, 1, 10, 
  1600.      win->sphere_depth, 0);
  1601.  
  1602.   /* Separator and buttons for dialog box. */
  1603.   dialog_sep = XmxMakeHorizontalSeparator (control_form);
  1604.   buttons_form = XmxMakeFormAndOneButton
  1605.     (control_form, GUIsphereOKButtonCB, "OK", 0);
  1606.   
  1607.   /* Constraints for control_form. */
  1608.   XmxSetArg (XmNtopOffset, 10);
  1609.   XmxSetConstraints 
  1610.     (size_label, XmATTACH_FORM, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_NONE,
  1611.      NULL, NULL, NULL, NULL);
  1612.   XmxSetArg (XmNtopOffset, 10);
  1613.   XmxSetConstraints
  1614.     (box->size_text, XmATTACH_FORM, XmATTACH_NONE, 
  1615.      XmATTACH_NONE, XmATTACH_FORM,
  1616.      NULL, NULL, NULL, NULL);
  1617.  
  1618.   XmxSetArg (XmNtopOffset, 10);
  1619.   XmxSetConstraints
  1620.     (mid_sep, XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_FORM,
  1621.      box->size_text, NULL, NULL, NULL);
  1622.   
  1623.   XmxSetConstraints
  1624.     (depth_label, XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_NONE,
  1625.      mid_sep, NULL, NULL, NULL);
  1626.   XmxSetArg (XmNbottomOffset, 10);
  1627.   XmxSetConstraints
  1628.     (box->depth_scale, XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_FORM,
  1629.      XmATTACH_FORM, depth_label, NULL, NULL, NULL);
  1630.   XmxSetArg (XmNtopOffset, 10);
  1631.   XmxSetConstraints
  1632.     (dialog_sep, XmATTACH_WIDGET, XmATTACH_WIDGET, XmATTACH_FORM,
  1633.      XmATTACH_FORM, box->depth_scale, buttons_form, NULL, NULL);
  1634.   XmxSetConstraints
  1635.     (buttons_form, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_FORM, XmATTACH_FORM,
  1636.      NULL, NULL, NULL, NULL);
  1637.  
  1638.   return box;
  1639. }
  1640.  
  1641.  
  1642.  
  1643. /* ------------------------------------------------------------------------ */
  1644. /* --------------------------- MENUBAR CALLBACK --------------------------- */
  1645. /* ------------------------------------------------------------------------ */
  1646. static XmxCallback (GUIrayBoxCB)
  1647. {
  1648.   char *fname;
  1649.   char line[MAXLINELEN];
  1650.  
  1651.   PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/tennis.aiff");
  1652.   
  1653.   fname = (char *)PVMALLOC (128 * sizeof (char));
  1654.  
  1655.   XmStringGetLtoR (((XmFileSelectionBoxCallbackStruct *)call_data)->value,
  1656.                    XmSTRING_DEFAULT_CHARSET,
  1657.                    &fname);
  1658.  
  1659.   sprintf (line, "save ray %s\0", fname);
  1660.   parse_line (gstate, line, TRUE);
  1661.  
  1662.   free (fname);
  1663.   XtUnmanageChild (w);
  1664.  
  1665.   return;
  1666. }
  1667.  
  1668. static XmxCallback (GUIrgbBoxCB)
  1669. {
  1670.   char *fname;
  1671.   char line[MAXLINELEN];
  1672.  
  1673.   XtUnmanageChild (w);
  1674.   XSync(XtDisplay(w),False);
  1675.  
  1676.   PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/tennis.aiff");
  1677.   
  1678.   fname = (char *)PVMALLOC (128 * sizeof (char));
  1679.  
  1680.   XmStringGetLtoR (((XmFileSelectionBoxCallbackStruct *)call_data)->value,
  1681.                    XmSTRING_DEFAULT_CHARSET,
  1682.                    &fname);
  1683.  
  1684.   sprintf (line, "save rgb %s", fname);
  1685.   sleep(1);
  1686.   parse_line (gstate, line, TRUE);
  1687.  
  1688.   free (fname);
  1689.  
  1690.   return;
  1691. }
  1692.  
  1693. #ifdef RENDERMAN
  1694. static XmxCallback (GUIrmBoxCB)
  1695. {
  1696.   char *fname;
  1697.   char line[MAXLINELEN];
  1698.  
  1699.   PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/tennis.aiff");
  1700.   
  1701.   fname = (char *)PVMALLOC (128 * sizeof (char));
  1702.  
  1703.   XmStringGetLtoR (((XmFileSelectionBoxCallbackStruct *)call_data)->value,
  1704.                    XmSTRING_DEFAULT_CHARSET,
  1705.                    &fname);
  1706.  
  1707.   sprintf (line, "save renderman %s\0", fname);
  1708.   parse_line (gstate, line, TRUE);
  1709.  
  1710.   free (fname);
  1711.   XtUnmanageChild (w);
  1712.  
  1713.   return;
  1714. }
  1715. #endif /* RENDERMAN */
  1716.  
  1717.  
  1718. static char *timeout_str;
  1719.  
  1720. static XmxCallback (GUIhdfTimeout)
  1721. {
  1722.   parse_line (gstate, timeout_str, TRUE);
  1723.   
  1724.   return;
  1725. }
  1726.  
  1727.  
  1728. static XmxCallback (GUIhdfBoxCB)
  1729. {
  1730.   char *fname;
  1731.   static char line[MAXLINELEN];
  1732.  
  1733.   PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/tennis.aiff");
  1734.  
  1735.   XtUnmanageChild (w);
  1736.  
  1737.   set_redraw 
  1738.     (gstate, find_window_by_id (gstate, XmxExtractUniqid ((int)client_data)));
  1739.   redraw_windows (gstate);
  1740.   
  1741.   fname = (char *)PVMALLOC (128 * sizeof (char));
  1742.  
  1743.   XmStringGetLtoR (((XmFileSelectionBoxCallbackStruct *)call_data)->value,
  1744.                    XmSTRING_DEFAULT_CHARSET,
  1745.                    &fname);
  1746.  
  1747.   sprintf (line, "save image %s\0", fname);
  1748.   timeout_str = line;
  1749.  
  1750.   free (fname);
  1751.  
  1752.   /* Since the box doesn't go away until we've reentered the main loop,
  1753.      make sure we come back and actually issue the save image
  1754.      command.  Boy, Motif is fun. */
  1755.   XtAppAddTimeOut (gstate->app_context, 1000, GUIhdfTimeout, True);
  1756.  
  1757.   return;
  1758. }
  1759.  
  1760.  
  1761. XmxCallback (GUIpolyviewMenubarCB)
  1762. {
  1763.   window_t *win;
  1764.   polyview_t *pv;
  1765.   char line[MAXLINELEN];
  1766.  
  1767.   /* Go get the window from the state's window list. */
  1768.   win = find_window_by_id (gstate, XmxExtractUniqid ((int)client_data));
  1769.   assert (win != NULL);
  1770.   
  1771.   /* Make the window active; this won't put an 'activate window'
  1772.      message in the history list, which is how Polyview 2.0 works. */
  1773.   if (win != gstate->active_windows)
  1774.     win_activate (gstate, win);
  1775.  
  1776.   pv = (polyview_t *)WIN_IMAGE(win);
  1777.  
  1778.   switch (XmxExtractToken ((int)client_data))
  1779.     {
  1780.     case PV_PVIEW_LOAD_VSET:
  1781.       PLAYAFILE ("/usr/lib/sounds/prosonus/musictags/slinky_slap.aiff");
  1782.       if (pv->loadVsetBox == NULL)
  1783.         pv->loadVsetBox = GUIcreateLoadVsetBox (gstate, win);
  1784.       else
  1785.         XmFileSelectionDoSearch (pv->loadVsetBox->base, NULL);
  1786.       XmxManageRemanage (pv->loadVsetBox->base);
  1787.       break;
  1788.  
  1789.     case PV_PVIEW_DTM_SEND:
  1790.       parse_line (gstate, "dtm send", TRUE);
  1791.       break;
  1792.     case PV_PVIEW_DATA_LOAD:
  1793.       parse_line (gstate, "data load", TRUE);
  1794.       break;
  1795.     case PV_PVIEW_DATA_NORMALIZE:
  1796.       parse_line (gstate, "data normalize", TRUE);
  1797.       break;
  1798.  
  1799.     case PV_PVIEW_SAVE_RAY:
  1800.       if (pv->ray_box == NULL)
  1801.         {
  1802.           XmxSetUniqid (XmxExtractUniqid ((int)client_data));
  1803.           pv->ray_box = XmxMakeFileSBDialog
  1804.             (win->base, "Save Rayshade File",
  1805.              "Enter filename for Rayshade file:",
  1806.              GUIrayBoxCB, 0);
  1807.         }
  1808.       else
  1809.         XmFileSelectionDoSearch (pv->ray_box, NULL);
  1810.       XmxManageRemanage (pv->ray_box);
  1811.       break;
  1812.     case PV_PVIEW_SAVE_RGB:
  1813.       if (pv->rgb_box == NULL)
  1814.         {
  1815.           XmxSetUniqid (XmxExtractUniqid ((int)client_data));
  1816.           pv->rgb_box = XmxMakeFileSBDialog
  1817.             (win->base, "Save RGB File",
  1818.              "Enter filename for RGB file:",
  1819.              GUIrgbBoxCB, 0);
  1820.         }
  1821.       else
  1822.         XmFileSelectionDoSearch (pv->rgb_box, NULL);
  1823.       XmxManageRemanage (pv->rgb_box);
  1824.       break;
  1825. #ifdef RENDERMAN
  1826.     case PV_PVIEW_SAVE_RENDERMAN:
  1827.       if (pv->rm_box == NULL)
  1828.         {
  1829.           XmxSetUniqid (XmxExtractUniqid ((int)client_data));
  1830.           pv->rm_box = XmxMakeFileSBDialog
  1831.             (win->base, "Save Renderman File",
  1832.              "Enter filename for Renderman file:",
  1833.              GUIrmBoxCB, 0);
  1834.         }
  1835.       else
  1836.         XmFileSelectionDoSearch (pv->rm_box, NULL);
  1837.       XmxManageRemanage (pv->rm_box);
  1838.       break;
  1839. #endif /* RENDERMAN */
  1840.  
  1841.     case PV_PVIEW_SAVE_HDF:
  1842.       if (pv->hdf_box == NULL)
  1843.         {
  1844.           XmxSetUniqid (XmxExtractUniqid ((int)client_data));
  1845.           pv->hdf_box = XmxMakeFileSBDialog
  1846.             (win->base, "Save HDF Image",
  1847.              "Enter filename for HDF image:",
  1848.              GUIhdfBoxCB, 0);
  1849.         }
  1850.       else
  1851.         XmFileSelectionDoSearch (pv->hdf_box, NULL);
  1852.       XmxManageRemanage (pv->hdf_box);
  1853.       break;
  1854.       
  1855.     case PV_PVIEW_RESET:
  1856.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/tennis.aiff");
  1857.       parse_line (gstate, "reset", TRUE);
  1858.       break;
  1859.     case PV_PVIEW_CLOSE_WINDOW:
  1860.       /* NO!  This should close by id but fake the history list.
  1861.          Compromise between script shit and interactive use -- interactive
  1862.          integrity is more important than super-flexible scripts. */
  1863.       sprintf (line, "window close polyview \"%s\"", win->name);
  1864.       parse_line (gstate, line, TRUE);
  1865.       break;
  1866.  
  1867.     case PV_PROPS_FOCUS:
  1868.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/click2.aiff");
  1869.       parse_line (gstate, "props focus toggle", TRUE);
  1870.       break;
  1871.  
  1872.     case PV_PVIEW_TIME_FORWARD:
  1873.       PLAYAFILE ("/usr/lib/sounds/prosonus/instr/braz_hi_shaker.aiff");
  1874.       parse_line (gstate, "time forward", TRUE);
  1875.       break;
  1876.     case PV_PVIEW_TIME_FORWARDSTEP:
  1877.       PLAYAFILE ("/usr/lib/sounds/prosonus/instr/drm_clave.aiff");
  1878.       parse_line (gstate, "time forward step", TRUE);
  1879.       break;
  1880.     case PV_PVIEW_TIME_STOP:
  1881.       PLAYAFILE ("/usr/lib/sounds/prosonus/instr/tama_base_drm.aiff");
  1882.       parse_line (gstate, "time stop", TRUE);
  1883.       break;
  1884.     case PV_PVIEW_TIME_REVERSESTEP:
  1885.       PLAYAFILE ("/usr/lib/sounds/prosonus/instr/drm_clave.aiff");
  1886.       parse_line (gstate, "time reverse step", TRUE);
  1887.       break;
  1888.     case PV_PVIEW_TIME_REVERSE:
  1889.       PLAYAFILE ("/usr/lib/sounds/prosonus/instr/braz_hi_shaker.aiff");
  1890.       parse_line (gstate, "time reverse", TRUE);
  1891.       break;
  1892.     case PV_PVIEW_TIME_RESET:
  1893.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/tennis.aiff");
  1894.       parse_line (gstate, "time reset", TRUE);
  1895.       break;
  1896.  
  1897.     case PV_PVIEW_DRAW_VERTICES:
  1898.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  1899.       parse_line (gstate, "draw vertices", TRUE);
  1900.       break;
  1901.     case PV_PVIEW_DRAW_EDGES:
  1902.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  1903.       parse_line (gstate, "draw edges", TRUE);
  1904.       break;
  1905.     case PV_PVIEW_DRAW_HIDDEN:
  1906.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  1907.       parse_line (gstate, "draw hidden", TRUE);
  1908.       break;
  1909.     case PV_PVIEW_DRAW_FACES:
  1910.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  1911.       parse_line (gstate, "draw faces", TRUE);
  1912.       break;
  1913.     case PV_PVIEW_DRAW_OUTFACES:
  1914.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  1915.       parse_line (gstate, "draw outlined", TRUE);
  1916.       break;
  1917.  
  1918.     case PV_PVIEW_DRAG_NOTHING:
  1919.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  1920.       parse_line (gstate, "drag nothing", TRUE);
  1921.       break;
  1922.     case PV_PVIEW_DRAG_BOX:
  1923.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  1924.       parse_line (gstate, "drag box", TRUE);
  1925.       break;
  1926.     case PV_PVIEW_DRAG_VERTICES:
  1927.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  1928.       parse_line (gstate, "drag vertices", TRUE);
  1929.       break;
  1930.     case PV_PVIEW_DRAG_EDGES:
  1931.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  1932.       parse_line (gstate, "drag edges", TRUE);
  1933.       break;
  1934.     case PV_PVIEW_DRAG_HIDDEN:
  1935.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  1936.       parse_line (gstate, "drag hidden", TRUE);
  1937.       break;
  1938.     case PV_PVIEW_DRAG_FACES:
  1939.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  1940.       parse_line (gstate, "drag faces", TRUE);
  1941.       break;
  1942.     case PV_PVIEW_DRAG_OUTFACES:
  1943.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  1944.       parse_line (gstate, "drag outlined", TRUE);
  1945.       break;
  1946.     case PV_PVIEW_DRAG_SAMEASDRAW:
  1947.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  1948.       parse_line (gstate, "drag same_as_draw", TRUE);
  1949.       break;
  1950.  
  1951.     case PV_PVIEW_PROJ_PERSPECTIVE:
  1952.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  1953.       parse_line (gstate, "draw perspective", TRUE);
  1954.       break;
  1955.     case PV_PVIEW_PROJ_ORTHOGRAPHIC:
  1956.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  1957.       parse_line (gstate, "draw orthographic", TRUE);
  1958.       break;
  1959.     case PV_PVIEW_SHADE_GOURAUD:
  1960.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  1961.       parse_line (gstate, "draw gouraud", TRUE);
  1962.       break;
  1963.     case PV_PVIEW_SHADE_FLAT:
  1964.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  1965.       parse_line (gstate, "draw flat", TRUE);
  1966.       break;
  1967.  
  1968.     case PV_PVIEW_LIGHT_ONE:
  1969.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  1970.       parse_line (gstate, "light one", TRUE);
  1971.       break;
  1972.     case PV_PVIEW_LIGHT_TWO:
  1973.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  1974.       parse_line (gstate, "light two", TRUE);
  1975.       break;
  1976.     case PV_PVIEW_LIGHT_THREE:
  1977.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  1978.       parse_line (gstate, "light three", TRUE);
  1979.       break;
  1980.     case PV_PVIEW_LIGHT_X:
  1981.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  1982.       parse_line (gstate, "light x", TRUE);
  1983.       break;
  1984.     case PV_PVIEW_LIGHT_Y:
  1985.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  1986.       parse_line (gstate, "light y", TRUE);
  1987.       break;
  1988.     case PV_PVIEW_LIGHT_Z:
  1989.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  1990.       parse_line (gstate, "light z", TRUE);
  1991.       break;
  1992.     case PV_PVIEW_LIGHT_OFF:
  1993.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  1994.       parse_line (gstate, "light off", TRUE);
  1995.       break;
  1996.     case PV_PVIEW_LIGHT_TWOSIDE:
  1997.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/click2.aiff");
  1998.       (((XmToggleButtonCallbackStruct *)(call_data))->set) ?
  1999.         parse_line (gstate, "light twoside on", TRUE) :
  2000.           parse_line (gstate, "light twoside off", TRUE);
  2001.       break;
  2002.  
  2003.     case PV_PROPS_AXES_SMALL:
  2004.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  2005.       parse_line (gstate, "props axes small", TRUE);
  2006.       break;
  2007.     case PV_PROPS_AXES_LARGE:
  2008.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  2009.       parse_line (gstate, "props axes large", TRUE);
  2010.       break;
  2011.     case PV_PROPS_AXES_OFF:
  2012.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  2013.       parse_line (gstate, "props axes off", TRUE);
  2014.       break;
  2015.  
  2016.     case PV_PROPS_BOX_EDGESFACES:
  2017.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  2018.       parse_line (gstate, "props box all", TRUE);
  2019.       break;
  2020.     case PV_PROPS_BOX_FACES:
  2021.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/click2.aiff");
  2022.       parse_line (gstate, "props box faces", TRUE);
  2023.       break;
  2024.     case PV_PROPS_BOX_EDGES:
  2025.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/click2.aiff");
  2026.       parse_line (gstate, "props box edges", TRUE);
  2027.       break;
  2028.     case PV_PROPS_BOX_OFF:
  2029.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  2030.       parse_line (gstate, "props box off", TRUE);
  2031.       break;
  2032.  
  2033.     case PV_PROPS_GRID_ALL:
  2034.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  2035.       parse_line (gstate, "props grid all", TRUE);
  2036.       break;
  2037.     case PV_PROPS_GRID_XY:
  2038.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/click2.aiff");
  2039.       parse_line (gstate, "props grid xy", TRUE);
  2040.       break;
  2041.     case PV_PROPS_GRID_YZ:
  2042.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/click2.aiff");
  2043.       parse_line (gstate, "props grid yz", TRUE);
  2044.       break;
  2045.     case PV_PROPS_GRID_XZ:
  2046.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/click2.aiff");
  2047.       parse_line (gstate, "props grid xz", TRUE);
  2048.       break;
  2049.     case PV_PROPS_GRID_OFF:
  2050.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  2051.       parse_line (gstate, "props grid off", TRUE);
  2052.       break;
  2053.  
  2054.     case PV_PROPS_SHADOW_ALL:
  2055.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  2056.       parse_line (gstate, "props shadow all", TRUE);
  2057.       break;
  2058.     case PV_PROPS_SHADOW_XY:
  2059.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/click2.aiff");
  2060.       parse_line (gstate, "props shadow xy", TRUE);
  2061.       break;
  2062.     case PV_PROPS_SHADOW_YZ:
  2063.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/click2.aiff");
  2064.       parse_line (gstate, "props shadow yz", TRUE);
  2065.       break;
  2066.     case PV_PROPS_SHADOW_XZ:
  2067.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/click2.aiff");
  2068.       parse_line (gstate, "props shadow xz", TRUE);
  2069.       break;
  2070.     case PV_PROPS_SHADOW_OFF:
  2071.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  2072.       parse_line (gstate, "props shadow off", TRUE);
  2073.       break;
  2074.  
  2075.     case PV_PROPS_LEGEND:
  2076.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/click2.aiff");
  2077.       (((XmToggleButtonCallbackStruct *)(call_data))->set) ?
  2078.         parse_line (gstate, "props legend on", TRUE) :
  2079.           parse_line (gstate, "props legend off", TRUE);
  2080.       break;
  2081.  
  2082.     case PV_PROPS_CREDITS:
  2083.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/click2.aiff");
  2084.       (((XmToggleButtonCallbackStruct *)(call_data))->set) ?
  2085.         parse_line (gstate, "props credits on", TRUE) :
  2086.           parse_line (gstate, "props credits off", TRUE);
  2087.       break;
  2088.       
  2089.     case PV_PROPS_ALL_OFF:
  2090.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/tennis.aiff");
  2091.       parse_line (gstate, "props all off", TRUE);
  2092.       break;
  2093.  
  2094.     case PV_PVIEW_SELECT_VERTICES:
  2095.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  2096.       parse_line (gstate, "select vertices", TRUE);
  2097.       break;
  2098.     case PV_PVIEW_SELECT_FACES:
  2099.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  2100.       parse_line (gstate, "select faces", TRUE);
  2101.       break;
  2102.     case PV_PVIEW_SELECT_OBJECTS:
  2103.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/door_slam.aiff");
  2104.       parse_line (gstate, "select objects", TRUE);
  2105.       break;
  2106.     case PV_PVIEW_SELECT_ALL:
  2107.       PLAYAFILE ("/usr/lib/sounds/prosonus/sfx/tennis.aiff");
  2108.       parse_line (gstate, "select all", TRUE);
  2109.       break;
  2110.  
  2111.     case PV_PVIEW_POPUP_OUTLINE:
  2112.       if (pv->outlineBox == NULL)
  2113.         pv->outlineBox = GUIcreateOutlineBox (gstate, win);
  2114.       XmxManageRemanage (pv->outlineBox->base);
  2115.       break;
  2116.     case PV_PVIEW_POPUP_LINEWIDTH:
  2117.       if (pv->linewidthBox == NULL)
  2118.         pv->linewidthBox = GUIcreateLinewidthBox (gstate, win);
  2119.       XmxManageRemanage (pv->linewidthBox->base);
  2120.       break;
  2121.     case PV_PVIEW_POPUP_SPHERE:
  2122.       if (pv->sphereBox == NULL)
  2123.         pv->sphereBox = GUIcreateSphereBox (gstate, win);
  2124.       XmxManageRemanage (pv->sphereBox->base);
  2125.       break;
  2126.       
  2127.     case PV_PVIEW_HELP_ONWINDOW:
  2128.       GUIdoHelp (PV_PVIEW_HELP_ONWINDOW);
  2129. #if 0
  2130.       XmUpdateDisplay (gstate->base);
  2131.       PLAYAFILE ("pvpoly.aiff");
  2132. #endif
  2133.       break;
  2134.     }
  2135.  
  2136.   return;
  2137. }
  2138.  
  2139.  
  2140.  
  2141. /* ------------------------- GUIpolyviewWindowCB -------------------------- */
  2142. XmxCallback (GUIpolyviewWindowCB)
  2143. {
  2144.   window_t *win;
  2145.   polyview_t *pv;
  2146.  
  2147.   /* Go get the window from the state's window list. */
  2148.   win = find_window_by_id (gstate, XmxExtractUniqid ((int)client_data));
  2149.   assert (win != NULL);
  2150.   
  2151.   /* Make the window active; this won't put an 'activate window'
  2152.      message in the history list, which is how Polyview 2.0 works. */
  2153.   /* ALWAYS make this window active in this case, because of 'activate'
  2154.      toggle below.  This is kinda screwy, but it works. */
  2155.   win_activate (gstate, win);
  2156.   
  2157.   pv = (polyview_t *)WIN_IMAGE(win);
  2158.   
  2159.   /* Handle active/private and blast. */
  2160.   switch (XmxExtractToken ((int)client_data))
  2161.     {
  2162.     case PV_PVIEW_BLAST:
  2163.       PLAYAFILE ("/usr/lib/sounds/prosonus/musictags/jar.aiff");
  2164.       parse_line (gstate, "blast image", TRUE);
  2165.       break;
  2166.     case PV_PVIEW_ACTIVE:
  2167.       /* Never let the user make a window inactive -- making this
  2168.          window active, above, should handle that. */
  2169.       PLAYAFILE ("/usr/lib/sounds/prosonus/instr/conga_hi_rim.aiff");
  2170.       break;
  2171.     case PV_PVIEW_PRIVATE:
  2172.       PLAYAFILE ("/usr/lib/sounds/prosonus/instr/conga_hi_rim.aiff");
  2173.       break;
  2174.     }
  2175.  
  2176.   return;
  2177. }
  2178.  
  2179.  
  2180.  
  2181. /* ------------------------------------------------------------------------ */
  2182. /* ---------------------------- EVENT HANDLERS ---------------------------- */
  2183. /* ------------------------------------------------------------------------ */
  2184.  
  2185. /* File-local variables for picking mode; unclean, but what
  2186.    the hell, we'll never be picking in more than one window
  2187.    at a time anyway. */
  2188. static long ix, iy;
  2189. static long cx, cy;
  2190. static long px, py;
  2191.  
  2192. /* We gotta store the goddamn animation parameters locally
  2193.    and set the real ones to 0 in pick mode, else picking won't
  2194.    work with 'time forward' going. */
  2195. static long temp_forward, temp_reverse;
  2196.  
  2197.  
  2198.  
  2199.  
  2200. /* ---------------------- GUIpolyviewMotion1Handler ----------------------- */
  2201. static XmxEventHandler (GUIpolyviewMotion1Handler)
  2202. {
  2203.   /* We get any button-1-down-with-motion events. */
  2204.   window_t *win;
  2205.   polyview_t *pv;
  2206.  
  2207.   /* Do the pick shit. */
  2208.   if (event->xmotion.state & Button1MotionMask)
  2209.     {
  2210.       /* Go get the window from the state's window list. */
  2211.       win = find_window_by_id (gstate, XmxExtractUniqid ((int)client_data));
  2212.       assert (win != NULL);
  2213.  
  2214.       pv = (polyview_t *)WIN_IMAGE(win);
  2215.       
  2216.       /* Get the new mouse location. */
  2217.       cx = event->xmotion.x;
  2218.       cy = pv->dv_height - 1 - event->xmotion.y;
  2219.       
  2220.       /* If the mouse has moved, redraw the rubber band box and */
  2221.       /* test label. */
  2222.       if ((px != cx) || (py != cy)) 
  2223.         {
  2224. #ifdef __sgi
  2225.           /* Erase the old rubberband box and draw the new box. */
  2226.           color (0);
  2227.           recti(ix, iy, px, py);
  2228.           color (1);
  2229.           recti(ix, iy, cx, cy);
  2230.           
  2231.           /* Place the type of operation in the window. */
  2232.           cmov2i(2,2);
  2233.           switch (win->pickmode) 
  2234.             {
  2235.             case PICK_VERTEX:
  2236.               charstr("PICK VERTEX");
  2237.               break;
  2238.             case PICK_EDGE:
  2239.               charstr("PICK EDGE");
  2240.               break;
  2241.             case PICK_FACE:
  2242.               charstr("PICK FACE");
  2243.               break;
  2244.             case PICK_OBJECT:
  2245.               charstr("PICK OBJECT");
  2246.               break;
  2247.             }
  2248. #endif /* __sgi */
  2249.           
  2250.           /* Update the "previous" mouse position. */
  2251.           px = cx;
  2252.           py = cy;
  2253.         }
  2254.     }
  2255.   
  2256.   return;
  2257. }
  2258.  
  2259.  
  2260.  
  2261. /* ---------------------- GUIpolyviewMotion2Handler ----------------------- */
  2262. static XmxEventHandler (GUIpolyviewMotion2Handler)
  2263. {
  2264.   /* We get any button-down-with-motion events. */
  2265.   window_t *win;
  2266.   polyview_t *pv;
  2267.  
  2268.   float CM[DIMS], V[DIMS];
  2269.   float old_half;
  2270.   int shft_tmp;
  2271.  
  2272.   /* Rotate scene. */
  2273.   if (event->xmotion.state & Button2MotionMask)
  2274.     {
  2275.       /* Go get the window from the state's window list. */
  2276.       win = find_window_by_id (gstate, XmxExtractUniqid ((int)client_data));
  2277.       assert (win != NULL);
  2278.  
  2279.       pv = (polyview_t *)WIN_IMAGE(win);
  2280.       
  2281.       /* We don't need to activate the window here, since it will have
  2282.          been activated in GUIpolyviewButtonPressHandler and we know
  2283.          that the active window's not going to be changed before the button
  2284.          is released. */
  2285.       
  2286.       /* Get the new mouse location. */
  2287.       CM[X] = event->xmotion.x;
  2288.       CM[Y] = pv->dv_height - 1 - event->xmotion.y;
  2289.  
  2290.       /* If shift key went up or down, do things. */
  2291.       if (win->shift_changed)
  2292.         {
  2293.           win->shift_changed = 0;
  2294.           win->CI[X] = CM[X];
  2295.           win->CI[Y] = CM[Y];
  2296.           win->rho_v = win->rho;
  2297.           win->theta_v = win->theta;
  2298.           win->phi_v = win->phi;
  2299.         }
  2300.       
  2301.       if (win->shifted) 
  2302.         {
  2303.           /* Calculate new from point. */
  2304.           win->rho = win->rho_v +
  2305.             WIN_MAXWIDTH(win)*(CM[Y] - win->CI[Y])/win->radius;
  2306.           if (win->rho < 0.05)
  2307.             win->rho = 0.05;
  2308.         }
  2309.       else 
  2310.         {
  2311.           win->theta = win->theta_v - PI*(CM[X]- win->CI[X])/win->radius;
  2312.           win->phi = win->phi_v + PI*(CM[Y]- win->CI[Y])/win->radius;
  2313.           
  2314.           old_half = win->half;
  2315.           win->half = fsin(win->phi);
  2316.  
  2317.           /* If the z axis is crossed, invert the twist value.
  2318.              Is this even consequential? */
  2319.           if (((win->half >= 0.0) && (old_half < 0.0)) ||
  2320.               ((win->half <= 0.0) && (old_half > 0.0))) 
  2321.             {
  2322.               win->twist_tmp = win->twist_tmp - 1800;
  2323.               if (win->twist_tmp < 0)
  2324.                 win->twist_tmp += 3600;
  2325.             }
  2326.         }
  2327.       
  2328.       sphere_to_cart(win->rho, win->theta, win->phi,
  2329.                      &V[X], &V[Y], &V[Z]);
  2330.  
  2331.       WIN_CFROM(win)[X] = WIN_AT(win)[X] + V[X];
  2332.       WIN_CFROM(win)[Y] = WIN_AT(win)[Y] + V[Y];
  2333.       WIN_CFROM(win)[Z] = WIN_AT(win)[Z] + V[Z];
  2334.       
  2335.       WIN_SFROM(win)[RHO] = win->rho;
  2336.       WIN_SFROM(win)[THETA] = win->theta;
  2337.       WIN_SFROM(win)[PHI] = win->phi;
  2338.       
  2339.       set_redraw (gstate, win);
  2340.     }
  2341.   
  2342.   return;
  2343. }
  2344.  
  2345.  
  2346.  
  2347.  
  2348.  
  2349.  
  2350. /* ------------------- GUIpolyviewButtonReleaseHandler ------------------- */
  2351. static XmxEventHandler (GUIpolyviewButtonReleaseHandler)
  2352. {
  2353.   window_t *win;
  2354.   polyview_t *pv;
  2355.   char line[MAXLINELEN];
  2356.  
  2357.   /* Go get the window from the state's window list. */
  2358.   win = find_window_by_id (gstate, XmxExtractUniqid ((int)client_data));
  2359.   assert (win != NULL);
  2360.   
  2361.   pv = (polyview_t *)WIN_IMAGE(win);
  2362.   
  2363.   /* Have to let Xmx know what this Uniqid is. */
  2364.   XmxSetUniqid (win->id);
  2365.   
  2366.   if (event->xbutton.button == Button1)
  2367.     {
  2368.       /* Remove the motion handler for this window --- we must match
  2369.          proc and client_data for this to work. */
  2370.       XmxRemoveEventHandler
  2371.         (pv->drawing_volume, Button1MotionMask, GUIpolyviewMotion1Handler, 0);
  2372.       /* Also commit suicide.  This should work... */
  2373.       XmxRemoveEventHandler
  2374.         (pv->drawing_volume, ButtonReleaseMask, 
  2375.          GUIpolyviewButtonReleaseHandler, 0);
  2376.  
  2377. #ifdef __sgi      
  2378.       /* We're still in overlay mode. */
  2379.       color (0);
  2380.       clear ();
  2381.       zbuffer (TRUE);
  2382. #endif /* __sgi */
  2383.       
  2384.       /* Pop out of overlay mode. */
  2385.       XmxWinset (pv->drawing_volume);
  2386.  
  2387.       /* This is a bad idea because we will have gone into single matrix
  2388.          mode and back out during pick, right? */
  2389.       popmatrix ();
  2390.       popviewport ();
  2391.  
  2392.       /* Ensure that ix < cx and iy < cy. */
  2393.       if (ix > cx) 
  2394.         {
  2395.           int temp = ix;
  2396.           ix = cx;
  2397.           cx = temp;
  2398.         }
  2399.       if (iy > cy) 
  2400.         {
  2401.           int temp = iy;
  2402.           iy = cy;
  2403.           cy = temp;
  2404.         }
  2405.       
  2406.       PickRegion (gstate, win, ix, iy, cx, cy, win->shifted, 0);
  2407.  
  2408.       /* Restore animation for this window. */
  2409.       WIN_FORWARD(win) = temp_forward;
  2410.       WIN_REVERSE(win) = temp_reverse;
  2411.  
  2412.       /* Turn actions back on. */
  2413.       gstate->no_actions = 0;
  2414.     }
  2415.   
  2416.   if (event->xbutton.button == Button2)
  2417.     {
  2418.       /* Remove the motion handler for this window --- we must match
  2419.          proc and client_data for this to work. */
  2420.       XmxRemoveEventHandler
  2421.         (pv->drawing_volume, Button2MotionMask, GUIpolyviewMotion2Handler, 0);
  2422.       /* Also commit suicide.  This should work... */
  2423.       XmxRemoveEventHandler
  2424.         (pv->drawing_volume, ButtonReleaseMask, 
  2425.          GUIpolyviewButtonReleaseHandler, 0);
  2426.  
  2427.       /* Echo the final position to the transcript file, if any. */
  2428.       /* Also add command to history list in command widget. */
  2429.       if (gstate->transcript_fp != NULL) 
  2430.         {
  2431.           fprintf(gstate->transcript_fp, "move camera %e %e %e %d\n",
  2432.                   WIN_CFROM(win)[X],
  2433.                   WIN_CFROM(win)[Y],
  2434.                   WIN_CFROM(win)[Z],
  2435.                   win->twist_tmp);
  2436.           fflush (gstate->transcript_fp);
  2437.         }
  2438.  
  2439.       sprintf (line, "move camera %e %e %e %d\0", 
  2440.                WIN_CFROM(win)[X],
  2441.                WIN_CFROM(win)[Y],
  2442.                WIN_CFROM(win)[Z],
  2443.                win->twist_tmp);
  2444.       GUIaddCommand (line);
  2445.  
  2446.       /* If a fast drawing function has been specified, undo it. */
  2447.       if (win->use_fastdraw) 
  2448.         {
  2449.           /* Turn off fast dragging and ask for yet another redraw. */
  2450.           win->use_fastdraw = FALSE;
  2451.           set_redraw(gstate, win);
  2452.         }
  2453.     }
  2454.   
  2455.   return;
  2456. }
  2457.  
  2458.  
  2459.  
  2460.  
  2461. /* -------------------- GUIpolyviewButtonPressHandler --------------------- */
  2462. static XmxEventHandler (GUIpolyviewButtonPressHandler)
  2463. {
  2464.   /* We get incoming button presses under the assumption that
  2465.      the appropriate motion handler hasn't been installed yet. */
  2466.   window_t *win;
  2467.   polyview_t *pv;
  2468.   
  2469.   /* Go get the window from the state's window list. */
  2470.   win = find_window_by_id (gstate, XmxExtractUniqid ((int)client_data));
  2471.   assert (win != NULL);
  2472.   
  2473.   /* Make the window active; this won't put an 'activate window'
  2474.      message in the history list, which is how Polyview 2.0 works. */
  2475.   if (win != gstate->active_windows)
  2476.     win_activate (gstate, win);
  2477.   
  2478.   pv = (polyview_t *)WIN_IMAGE(win);
  2479.   
  2480.   /* Use this window's uniqid for any event handlers. */
  2481.   XmxSetUniqid (win->id);
  2482.  
  2483.   /* Breakdown by button. */
  2484.   if (event->xbutton.button == Button1 && WinHasData (win))
  2485.     {
  2486.       XmxWinset (pv->drawing_volume);
  2487.  
  2488. #ifdef __sgi
  2489.       /* Go into overlay planes; no Zbuffer, and clear it out. */
  2490.       GLXwinset (XtDisplay (pv->drawing_volume),
  2491.                  overlayWindow (pv->drawing_volume));
  2492.       color (0);
  2493.       clear ();
  2494. #endif
  2495.  
  2496.       zbuffer (FALSE);
  2497.  
  2498.       pushviewport ();
  2499.       pushmatrix ();
  2500.       ortho2 (0.0, (float)(pv->dv_width), 0.0, (float)(pv->dv_height));
  2501.  
  2502.       /* Load static variables for initial position. */
  2503.       ix = cx = event->xbutton.x;
  2504.       iy = cy = pv->dv_height - 1 - event->xbutton.y;
  2505.  
  2506.       px = -1;
  2507.       py = -1;
  2508.  
  2509.       /* Now we're in picking mode.  Load up the
  2510.          event handlers. */
  2511.  
  2512.       /* Install the button 1 motion handler for this window. */
  2513.       XmxAddEventHandler
  2514.         (pv->drawing_volume, Button1MotionMask, GUIpolyviewMotion1Handler, 0);
  2515.       /* Install the button 1 release handler for this window. */
  2516.       XmxAddEventHandler
  2517.         (pv->drawing_volume, ButtonReleaseMask, 
  2518.          GUIpolyviewButtonReleaseHandler, 0);
  2519.  
  2520.       /* Store the animation parameters for this window and
  2521.          set 'em to 0. */
  2522.       temp_forward = WIN_FORWARD(win);
  2523.       temp_reverse = WIN_REVERSE(win);
  2524.       WIN_FORWARD(win) = WIN_REVERSE(win) = 0;
  2525.  
  2526.       /* Turn off actions. */
  2527.       gstate->no_actions = 1;
  2528.     }
  2529.   if (event->xbutton.button == Button2)
  2530.     {
  2531.       /* Install the button 2 motion handler for this window. */
  2532.       XmxAddEventHandler
  2533.         (pv->drawing_volume, Button2MotionMask, GUIpolyviewMotion2Handler, 0);
  2534.       /* Install the button 2 release handler for this window. */
  2535.       XmxAddEventHandler
  2536.         (pv->drawing_volume, ButtonReleaseMask, 
  2537.          GUIpolyviewButtonReleaseHandler, 0);
  2538.  
  2539.       /* If a fast drawing function has been specified for this
  2540.          window, then use it. */
  2541.       win->use_fastdraw = TRUE;
  2542.  
  2543.       /* Load initial calculations for transformation
  2544.          into the window struct. */
  2545.       win->radius = (float)MIN(win->cx, win->cy);
  2546.       win->CI[X] = (float)(event->xbutton.x);
  2547.       win->CI[Y] = (float)(pv->dv_height - 1 - event->xbutton.y);
  2548.       
  2549.       win->rho = WIN_SFROM(win)[RHO];
  2550.       win->theta = WIN_SFROM(win)[THETA];
  2551.       win->phi = WIN_SFROM(win)[PHI];
  2552.       
  2553.       win->rho_v = win->rho;
  2554.       win->theta_v = win->theta;
  2555.       win->phi_v = win->phi;
  2556.       
  2557.       win->half = sin (win->phi_v);
  2558.  
  2559.       /* Get a redraw at least to draw with the fastdraw function. */
  2560.       set_redraw (gstate, win);
  2561.     }
  2562.  
  2563.   return;
  2564. }
  2565.  
  2566.  
  2567. /* ------------------------------------------------------------------------ */
  2568. /* ------------------------------------------------------------------------ */
  2569. /* ------------------------------------------------------------------------ */
  2570.  
  2571. /* This is going to cause collisions between movement functionality
  2572.    of local and remote user, if they operate at the same time.
  2573.    That's because it's a hack, stupid. */
  2574. void remote_movecursor (state_t *state, window_t *win, float fx, float fy)
  2575. {
  2576.   int x = (int)fx, y = (int)fy;
  2577.   polyview_t *pv;
  2578.  
  2579.   fprintf (stderr, "CALLED %f %f %d %d\n", fx, fy, x, y);
  2580.  
  2581.   pv = (polyview_t *)WIN_IMAGE(win);
  2582.  
  2583.   /* Are we not moving yet? */
  2584.   if (win->use_fastdraw == FALSE)
  2585.     {
  2586.       /* If a fast drawing function has been specified for this
  2587.          window, then use it. */
  2588.       win->use_fastdraw = TRUE;
  2589.       
  2590.       /* Load initial calculations for transformation
  2591.          into the window struct. */
  2592.       win->radius = (float)MIN(win->cx, win->cy);
  2593.       win->CI[X] = (float)(x);
  2594.       win->CI[Y] = (float)(pv->dv_height - 1 - y);
  2595.       
  2596.       win->rho = WIN_SFROM(win)[RHO];
  2597.       win->theta = WIN_SFROM(win)[THETA];
  2598.       win->phi = WIN_SFROM(win)[PHI];
  2599.       
  2600.       win->rho_v = win->rho;
  2601.       win->theta_v = win->theta;
  2602.       win->phi_v = win->phi;
  2603.       
  2604.       win->half = sin (win->phi_v);
  2605.  
  2606.       /* Get a redraw at least to draw with the fastdraw function. */
  2607.       set_redraw (gstate, win);
  2608.     }
  2609.   else
  2610.     {
  2611.       float CM[DIMS], V[DIMS];
  2612.       float old_half;
  2613.       int shft_tmp;
  2614.       
  2615.       /* Actually move. */
  2616.       
  2617.       /* Get the new mouse location. */
  2618.       CM[X] = x;
  2619.       CM[Y] = pv->dv_height - 1 - y;
  2620.  
  2621.       win->theta = win->theta_v - PI*(CM[X]- win->CI[X])/win->radius;
  2622.       win->phi = win->phi_v + PI*(CM[Y]- win->CI[Y])/win->radius;
  2623.       
  2624.       old_half = win->half;
  2625.       win->half = fsin(win->phi);
  2626.       
  2627.       /* If the z axis is crossed, invert the twist value.
  2628.          Is this even consequential? */
  2629.       if (((win->half >= 0.0) && (old_half < 0.0)) ||
  2630.           ((win->half <= 0.0) && (old_half > 0.0))) 
  2631.         {
  2632.           win->twist_tmp = win->twist_tmp - 1800;
  2633.           if (win->twist_tmp < 0)
  2634.             win->twist_tmp += 3600;
  2635.         }
  2636.   
  2637.       sphere_to_cart(win->rho, win->theta, win->phi,
  2638.                      &V[X], &V[Y], &V[Z]);
  2639.  
  2640.       WIN_CFROM(win)[X] = WIN_AT(win)[X] + V[X];
  2641.       WIN_CFROM(win)[Y] = WIN_AT(win)[Y] + V[Y];
  2642.       WIN_CFROM(win)[Z] = WIN_AT(win)[Z] + V[Z];
  2643.       
  2644.       WIN_SFROM(win)[RHO] = win->rho;
  2645.       WIN_SFROM(win)[THETA] = win->theta;
  2646.       WIN_SFROM(win)[PHI] = win->phi;
  2647.       
  2648.       set_redraw (gstate, win);
  2649.     }
  2650.   
  2651.   return;
  2652. }
  2653.  
  2654.  
  2655. void remote_movecursorend (state_t *state, window_t *win)
  2656. {
  2657.   char line[MAXLINELEN];
  2658.   /* Echo the final position to the transcript file, if any. */
  2659.   /* Also add command to history list in command widget. */
  2660.   if (gstate->transcript_fp != NULL) 
  2661.     {
  2662.       fprintf(gstate->transcript_fp, "move camera %e %e %e %d\n",
  2663.               WIN_CFROM(win)[X],
  2664.               WIN_CFROM(win)[Y],
  2665.               WIN_CFROM(win)[Z],
  2666.               win->twist_tmp);
  2667.       fflush (gstate->transcript_fp);
  2668.     }
  2669.   
  2670.   sprintf (line, "move camera %e %e %e %d\0", 
  2671.            WIN_CFROM(win)[X],
  2672.            WIN_CFROM(win)[Y],
  2673.            WIN_CFROM(win)[Z],
  2674.            win->twist_tmp);
  2675.   GUIaddCommand (line);
  2676.   
  2677.   win->use_fastdraw = FALSE;
  2678.   set_redraw (gstate, win);
  2679.  
  2680.   return;
  2681. }
  2682.  
  2683.  
  2684.  
  2685. /* --------------------------- GUIpviewInputCB ---------------------------- */
  2686. #ifdef __sgi
  2687. static XmxCallback (GUIpviewInputCB)
  2688. {
  2689.   window_t *win;
  2690.   polyview_t *pv;
  2691.   int _bufsize = 3, _count;
  2692.   char _buffer[3];
  2693.   KeySym _key;
  2694.   XComposeStatus _cs;
  2695.   XEvent *event = ((XmDrawingAreaCallbackStruct *)call_data)->event;
  2696.  
  2697.   /* Go get the window from the state's window list. */
  2698.   win = find_window_by_id (gstate, XmxExtractUniqid ((int)client_data));
  2699.   assert (win != NULL);
  2700.   
  2701.   /* Make the window active; this won't put an 'activate window'
  2702.      message in the history list, which is how Polyview 2.0 works. */
  2703.   if (win != gstate->active_windows)
  2704.     win_activate (gstate, win);
  2705.   
  2706.   pv = (polyview_t *)WIN_IMAGE(win);
  2707.   
  2708.   if (((XmDrawingAreaCallbackStruct *)call_data)->reason == XmCR_INPUT)
  2709.     {
  2710.       if (event->xany.type == KeyPress)
  2711.         {
  2712.           /* Go get ascii translation. */
  2713.           _count = XLookupString (&(event->xkey), _buffer, _bufsize, 
  2714.                                   &_key, &_cs);
  2715.           
  2716.           /* Insert trailing Nil. */
  2717.           _buffer[_count] = '\0';
  2718.  
  2719.           /* Ah, let's just use the KeySym directly. */
  2720.           if (_key == XK_Shift_L || _key == XK_Shift_R)
  2721.             {
  2722.               win->shifted = 1;
  2723.               win->shift_changed = 1;
  2724.             }
  2725.  
  2726.         }
  2727.       else if (event->xany.type == KeyRelease)
  2728.         {
  2729.           /* Go get ascii translation. */
  2730.           _count = XLookupString (&(event->xkey), _buffer, _bufsize, 
  2731.                                   &_key, &_cs);
  2732.           
  2733.           /* Insert trailing Nil. */
  2734.           _buffer[_count] = '\0';
  2735.  
  2736.           /* Ah, let's just use the KeySym directly. */
  2737.           if (_key == XK_Shift_L || _key == XK_Shift_R)
  2738.             {
  2739.               win->shifted = 0;
  2740.               win->shift_changed = 1;
  2741.             }
  2742.  
  2743.         }
  2744.     }
  2745.  
  2746.   return;
  2747. }
  2748. #endif /* __sgi */
  2749.  
  2750.  
  2751.  
  2752. /* ------------------------------------------------------------------------ */
  2753. /* ---------------------------- MENUBAR STRUCT ---------------------------- */
  2754. /* ------------------------------------------------------------------------ */
  2755. static XmxMenubarStruct PviewFileMenu[] =
  2756. {
  2757.   { "Load Vset...",    'V', GUIpolyviewMenubarCB, PV_PVIEW_LOAD_VSET },
  2758.   { "Send Vset",       'S', GUIpolyviewMenubarCB, PV_PVIEW_DTM_SEND },
  2759.   { "----" },
  2760.   { "Data Load",       'L', GUIpolyviewMenubarCB, PV_PVIEW_DATA_LOAD },
  2761.   { "----" },
  2762.   { "Save HDF...",     'H', GUIpolyviewMenubarCB, PV_PVIEW_SAVE_HDF },
  2763.   { "Save Ray...",     'y', GUIpolyviewMenubarCB, PV_PVIEW_SAVE_RAY },
  2764.   { "Save RGB...",     'G', GUIpolyviewMenubarCB, PV_PVIEW_SAVE_RGB },
  2765. #ifdef RENDERMAN
  2766.   { "Save Renderman...",     'm', GUIpolyviewMenubarCB, PV_PVIEW_SAVE_RENDERMAN },
  2767. #endif
  2768.   { "----" },
  2769.   { "Reset",           'R', GUIpolyviewMenubarCB, PV_PVIEW_RESET },
  2770.   { "----" },
  2771.   { "Close Window",    'C', GUIpolyviewMenubarCB, PV_PVIEW_CLOSE_WINDOW },
  2772.   { "Exit Program...", 'E', GUImainMenubarCB,     PV_EXIT_PROGRAM },
  2773.   { NULL },
  2774. };
  2775.  
  2776. static XmxMenubarStruct PviewWindowsMenu[] =
  2777. {
  2778.   { "Open Polyview...", 'O', GUImainMenubarCB, PV_OPEN_POLYVIEW },
  2779.   { "Open Palette...",  'P', GUImainMenubarCB, PV_OPEN_PALETTE },
  2780.   { "Open Info...",     'I', GUImainMenubarCB, PV_OPEN_INFO },
  2781.   { "Open Time...",     'T', GUImainMenubarCB, PV_OPEN_TIME },
  2782.   { NULL },
  2783. };
  2784.  
  2785. static XmxMenubarStruct PviewDrawmodeMenu[] =
  2786. {
  2787.   { "<Vertices",       'V', GUIpolyviewMenubarCB, PV_PVIEW_DRAW_VERTICES },
  2788.   { "<Edges",          'E', GUIpolyviewMenubarCB, PV_PVIEW_DRAW_EDGES },
  2789.   { "<Hidden Edges",   'H', GUIpolyviewMenubarCB, PV_PVIEW_DRAW_HIDDEN },
  2790.   { "<Faces",          'F', GUIpolyviewMenubarCB, PV_PVIEW_DRAW_FACES },
  2791.   { "<Outlined Faces", 'O', GUIpolyviewMenubarCB, PV_PVIEW_DRAW_OUTFACES },
  2792.   { NULL },
  2793. };
  2794.  
  2795. static XmxMenubarStruct PviewDragmodeMenu[] =
  2796. {
  2797.   { "<Nothing",  'N', GUIpolyviewMenubarCB, PV_PVIEW_DRAG_NOTHING },
  2798.   { "<Box",      'B', GUIpolyviewMenubarCB, PV_PVIEW_DRAG_BOX },
  2799.   { "<Vertices", 'V', GUIpolyviewMenubarCB, PV_PVIEW_DRAG_VERTICES },
  2800.   { "<Edges",    'E', GUIpolyviewMenubarCB, PV_PVIEW_DRAG_EDGES },
  2801.   { "<Hidden Edges", 'H', GUIpolyviewMenubarCB, PV_PVIEW_DRAG_HIDDEN },
  2802.   { "<Faces",        'F', GUIpolyviewMenubarCB, PV_PVIEW_DRAG_FACES },
  2803.   { "<Outlined Faces", 'O', GUIpolyviewMenubarCB, PV_PVIEW_DRAG_OUTFACES },
  2804.   { "----" },
  2805.   { "<Same As Draw", 'S', GUIpolyviewMenubarCB, PV_PVIEW_DRAG_SAMEASDRAW },
  2806.   { NULL },
  2807. };
  2808.  
  2809.  
  2810. static XmxMenubarStruct PviewLightMenu[] =
  2811. {
  2812.   { "<Light Off",   'O', GUIpolyviewMenubarCB, PV_PVIEW_LIGHT_OFF },
  2813.   { "----" },
  2814.   { "<Light One",   'L', GUIpolyviewMenubarCB, PV_PVIEW_LIGHT_ONE },
  2815.   { "<Light Two",   'T', GUIpolyviewMenubarCB, PV_PVIEW_LIGHT_TWO },
  2816.   { "<Light Three", 'h', GUIpolyviewMenubarCB, PV_PVIEW_LIGHT_THREE },
  2817.   { "<Light X",     'X', GUIpolyviewMenubarCB, PV_PVIEW_LIGHT_X },
  2818.   { "<Light Y",     'Y', GUIpolyviewMenubarCB, PV_PVIEW_LIGHT_Y },
  2819.   { "<Light Z",     'Z', GUIpolyviewMenubarCB, PV_PVIEW_LIGHT_Z },
  2820.   { "----" },
  2821.   { "#TwoSide Light", 'S', GUIpolyviewMenubarCB, PV_PVIEW_LIGHT_TWOSIDE },
  2822.   { NULL },
  2823. };
  2824.  
  2825. static XmxMenubarStruct PviewProjMenu[] =
  2826. {
  2827.   { "<Perspective",  'P', GUIpolyviewMenubarCB, PV_PVIEW_PROJ_PERSPECTIVE },
  2828.   { "<Orthographic", 'O', GUIpolyviewMenubarCB, PV_PVIEW_PROJ_ORTHOGRAPHIC },
  2829.   { NULL },
  2830. };
  2831.  
  2832. static XmxMenubarStruct PviewShadeMenu[] =
  2833. {
  2834.   { "<Gouraud", 'G', GUIpolyviewMenubarCB, PV_PVIEW_SHADE_GOURAUD },
  2835.   { "<Flat",    'F', GUIpolyviewMenubarCB, PV_PVIEW_SHADE_FLAT },
  2836.   { NULL },
  2837. };
  2838.  
  2839.  
  2840. static XmxMenubarStruct PviewRenderMenu[] =
  2841. {
  2842.   { "Draw", 'D', NULL, NULL, PviewDrawmodeMenu },
  2843.   { "Drag", 'g', NULL, NULL, PviewDragmodeMenu },
  2844.   { "----" },
  2845.   { "Light", 'L', NULL, NULL, PviewLightMenu },
  2846.   { "----" },
  2847.   { "Line Width...",     'W', GUIpolyviewMenubarCB, PV_PVIEW_POPUP_LINEWIDTH },
  2848.   { "Outline Color...",  'O', GUIpolyviewMenubarCB, PV_PVIEW_POPUP_OUTLINE },
  2849.   { "Vertex Spheres...", 'S', GUIpolyviewMenubarCB, PV_PVIEW_POPUP_SPHERE },
  2850.   { "----" },
  2851.   { "Projection", 'P', NULL, NULL, PviewProjMenu },
  2852.   { "Shademodel", 'S', NULL, NULL, PviewShadeMenu },
  2853.   { NULL },
  2854. };
  2855.  
  2856. static XmxMenubarStruct PviewAxesMenu[] =
  2857. {
  2858.   { "<Large", 'L', GUIpolyviewMenubarCB, PV_PROPS_AXES_LARGE },
  2859.   { "<Small", 'S', GUIpolyviewMenubarCB, PV_PROPS_AXES_SMALL },
  2860.   { "----" },
  2861.   { "<Off",   'O', GUIpolyviewMenubarCB, PV_PROPS_AXES_OFF },
  2862.   { NULL },
  2863. };
  2864.  
  2865. static XmxMenubarStruct PviewBoxMenu[] =
  2866. {
  2867.   { "<All",   'A', GUIpolyviewMenubarCB, PV_PROPS_BOX_EDGESFACES },
  2868.   { "----" },
  2869.   { "<Faces", 'F', GUIpolyviewMenubarCB, PV_PROPS_BOX_FACES },
  2870.   { "<Edges", 'E', GUIpolyviewMenubarCB, PV_PROPS_BOX_EDGES },
  2871.   { "----" },
  2872.   { "<Off",   'O', GUIpolyviewMenubarCB, PV_PROPS_BOX_OFF },
  2873.   { NULL },
  2874. };
  2875.  
  2876. static XmxMenubarStruct PviewGridMenu[] =
  2877. {
  2878.   { "All", 'A', GUIpolyviewMenubarCB, PV_PROPS_GRID_ALL },
  2879.   { "----" },
  2880.   { "#X Y", 'X', GUIpolyviewMenubarCB, PV_PROPS_GRID_XY },
  2881.   { "#Y Z", 'Y', GUIpolyviewMenubarCB, PV_PROPS_GRID_YZ },
  2882.   { "#X Z", 'Z', GUIpolyviewMenubarCB, PV_PROPS_GRID_XZ },
  2883.   { "----" },
  2884.   { "Off", 'O', GUIpolyviewMenubarCB, PV_PROPS_GRID_OFF },
  2885.   { NULL },
  2886. };
  2887.  
  2888. static XmxMenubarStruct PviewShadowMenu[] =
  2889. {
  2890.   { "All", 'A', GUIpolyviewMenubarCB, PV_PROPS_SHADOW_ALL },
  2891.   { "----" },
  2892.   { "#X Y", 'X', GUIpolyviewMenubarCB, PV_PROPS_SHADOW_XY },
  2893.   { "#Y Z", 'Y', GUIpolyviewMenubarCB, PV_PROPS_SHADOW_YZ },
  2894.   { "#X Z", 'Z', GUIpolyviewMenubarCB, PV_PROPS_SHADOW_XZ },
  2895.   { "----" },
  2896.   { "Off", 'O', GUIpolyviewMenubarCB, PV_PROPS_SHADOW_OFF },
  2897.   { NULL },
  2898. };
  2899.  
  2900.  
  2901. static XmxMenubarStruct PviewPropsMenu[] =
  2902. {
  2903.   { "Axes",    'A', NULL, NULL, PviewAxesMenu },
  2904.   { "Box",     'B', NULL, NULL, PviewBoxMenu },
  2905.   { "Grid",    'G', NULL, NULL, PviewGridMenu },
  2906.   { "Shadow",  'S', NULL, NULL, PviewShadowMenu },
  2907.   { "#Legend", 'L', GUIpolyviewMenubarCB, PV_PROPS_LEGEND },
  2908.   { "#Credits", 'C', GUIpolyviewMenubarCB, PV_PROPS_CREDITS },
  2909.   { "----" },
  2910.   { "All Off", 'O', GUIpolyviewMenubarCB, PV_PROPS_ALL_OFF },
  2911.   { NULL },
  2912. };
  2913.  
  2914. static XmxMenubarStruct PviewTimeMenu[] =
  2915. {
  2916.   { "Forward",       'F', GUIpolyviewMenubarCB, PV_PVIEW_TIME_FORWARD },
  2917.   { "Forward Step",  'o', GUIpolyviewMenubarCB, PV_PVIEW_TIME_FORWARDSTEP },
  2918.   { "Stop",          'S', GUIpolyviewMenubarCB, PV_PVIEW_TIME_STOP },
  2919.   { "Reverse Step",  'e', GUIpolyviewMenubarCB, PV_PVIEW_TIME_REVERSESTEP },
  2920.   { "Reverse",       'R', GUIpolyviewMenubarCB, PV_PVIEW_TIME_REVERSE },
  2921.   { "----" },
  2922.   { "Reset",         't', GUIpolyviewMenubarCB, PV_PVIEW_TIME_RESET },
  2923.   { NULL },
  2924. };
  2925.  
  2926. static XmxMenubarStruct PviewSelectMenu[] =
  2927. {
  2928.   { "<Vertices", 'V', GUIpolyviewMenubarCB, PV_PVIEW_SELECT_VERTICES },
  2929.   { "<Faces",    'F', GUIpolyviewMenubarCB, PV_PVIEW_SELECT_FACES },
  2930.   { "<Objects",  'O', GUIpolyviewMenubarCB, PV_PVIEW_SELECT_OBJECTS },
  2931.   { "----" },
  2932.   { "All",       'A', GUIpolyviewMenubarCB, PV_PVIEW_SELECT_ALL },
  2933.   { NULL },
  2934. };
  2935.  
  2936. static XmxMenubarStruct PviewHelpMenu[] =
  2937. {
  2938.   { "About",       'A', GUImainMenubarCB,     PV_HELP_ABOUT },
  2939.   { "On Commands", 'C', GUImainMenubarCB,     PV_HELP_ONCOMMANDS},
  2940.   { "On Window",   'W', GUIpolyviewMenubarCB, PV_PVIEW_HELP_ONWINDOW },
  2941.   { NULL },
  2942. };
  2943.  
  2944. static XmxMenubarStruct PviewMenu[] = 
  2945. {
  2946.   { "File",    'F', NULL, NULL, PviewFileMenu },
  2947.   { "Windows", 'W', NULL, NULL, PviewWindowsMenu },
  2948.   { "Render",  'R', NULL, NULL, PviewRenderMenu },
  2949.   { "Props",   'P', NULL, NULL, PviewPropsMenu },
  2950.   { "Time",    'T', NULL, NULL, PviewTimeMenu },
  2951.   { "Select",  'S', NULL, NULL, PviewSelectMenu },
  2952.   { "Help",    'H', NULL, NULL, PviewHelpMenu },
  2953.   { NULL },
  2954. };
  2955.  
  2956.  
  2957.  
  2958. /* ------------------------------------------------------------------------ */
  2959. /* ------------------------- GL WIDGET CALLBACKS -------------------------- */
  2960. /* ------------------------------------------------------------------------ */
  2961.  
  2962. /* --------------------------- GUIpviewRedrawCB --------------------------- */
  2963. XmxCallback (GUIpviewRedrawCB)
  2964. {
  2965.   window_t *win;
  2966.   
  2967.   /* This should get us the window_t struct corresponding to the
  2968.      window that triggered the callback. */
  2969.   win = find_window_by_id (gstate, XmxExtractUniqid ((int)client_data));
  2970.   assert (win != NULL);
  2971.   
  2972.   set_redraw (gstate, win);
  2973.   
  2974.   return;
  2975. }
  2976.  
  2977.  
  2978.  
  2979. /* --------------------------- GUIpviewGinitCB ---------------------------- */
  2980. XmxCallback (GUIpviewGinitCB)
  2981. {
  2982.   window_t *win;
  2983.   polyview_t *pv;
  2984.   
  2985.   /* This should get us the window_t struct corresponding to the
  2986.      window that triggered the callback. */
  2987.   win = find_window_by_id (gstate, XmxExtractUniqid ((int)client_data));
  2988.   assert (win != NULL);
  2989.   
  2990.   /* Grab the polyview image for the window. */
  2991.   pv = (polyview_t *)WIN_IMAGE(win);
  2992.   
  2993.   /* ---> This callback is supposed to be hit when the Widget
  2994.           is first realized. */
  2995.   
  2996.   /* Focus on this window. */
  2997.   XmxWinset (w);
  2998.   
  2999.   /* Set up initial parameters. */
  3000.   doublebuffer ();
  3001.   RGBmode ();
  3002.   
  3003.   /* Set up zbuffering. */
  3004.   zbuffer(TRUE);
  3005.   
  3006.   /* Go into MVIEWING mode for lighting. */
  3007.   mmode (MVIEWING);
  3008.   
  3009. #ifdef __sgi
  3010.       XmxInstallColormapsWithOverlay (gstate->base, pv->drawing_volume);
  3011. #else /* not __sgi */
  3012.       XmxInstallColormaps (gstate->base, pv->drawing_volume);
  3013. #endif /* not __sgi */
  3014.   
  3015.   if (!(gstate->gl_initialized))
  3016.     {
  3017.       /* This is now different from the palette window... */
  3018.       gstate->gl_initialized = 1;
  3019.       
  3020.       /* Right now lighting and patterns init is here since we know 
  3021.          this is the first GL dialog to be opened. */
  3022.       init_lighting ();
  3023.       init_patterns ();
  3024.       init_zbuffer ();
  3025.     }
  3026.   
  3027.   /* Reverse orientation of Z-buffer (was 0x7fff..., 0). */
  3028.   lsetdepth (gstate->zmax, gstate->zmin);
  3029.   zfunction (ZF_GEQUAL);
  3030.   
  3031. #ifdef __sgi
  3032.   /* Handle the overlays. */
  3033.   GLXwinset (XtDisplay (w), overlayWindow (w));
  3034.   mapcolor (0, 0, 0, 0);
  3035.   mapcolor (1, 255, 255, 255);
  3036. #endif
  3037.   
  3038.   /* Go back to regular window, just to be safe. */
  3039.   XmxWinset (w);
  3040.   
  3041.   /* This should be all that's needed; the rest of the work takes
  3042.      place in redraw_polyview, right? */
  3043.   
  3044.   /* We get a redraw callback here. */
  3045.   
  3046.   return;
  3047. }
  3048.  
  3049.  
  3050.  
  3051. /* --------------------------- GUIpviewResizeCB --------------------------- */
  3052. XmxCallback (GUIpviewResizeCB)
  3053. {
  3054.   window_t *win;
  3055.   polyview_t *pv;
  3056.   
  3057.   /* This should get us the window_t struct corresponding to the
  3058.      window that triggered the callback. */
  3059.   win = find_window_by_id (gstate, XmxExtractUniqid ((int)client_data));
  3060.   assert (win != NULL);
  3061.   
  3062.   /* Grab the polyview image for the window. */
  3063.   pv = (polyview_t *)WIN_IMAGE(win);
  3064.   
  3065.   /* Do a GL focus on the window as we get it from the callback. */
  3066.   XmxWinset (w);
  3067.   
  3068.   /* Store the new width and height in the window image. */
  3069. #ifdef __sgi
  3070.   pv->dv_width = ((GlxDrawCallbackStruct *)call_data)->width;
  3071.   pv->dv_height = ((GlxDrawCallbackStruct *)call_data)->height;
  3072. #endif
  3073.   
  3074. #ifdef _IBMR2
  3075.   {
  3076.     Dimension x, y;
  3077.     XmxSetArg (XmNwidth, &x);
  3078.     XmxSetArg (XmNheight, &y);
  3079.     XtGetValues (w, Xmx_wargs, Xmx_n);
  3080.     pv->dv_width = x;
  3081.     pv->dv_height = y;
  3082.   }
  3083. #endif
  3084.   
  3085.   /* Go update the rest of Calvert's data structures. */
  3086.   win->width = pv->dv_width;
  3087.   win->height = pv->dv_height;
  3088.   win->cx = win->width / 2;
  3089.   win->cy = win->height / 2;
  3090.   
  3091.   /* Explicitly avoid reshapeviewport by retrieving new
  3092.      geometry from call_data. */
  3093.   viewport
  3094.     (0, (Screencoord)pv->dv_width - 1, 0, (Screencoord)pv->dv_height - 1);
  3095.   
  3096. #ifdef __sgi
  3097.   /* Repeat the process for the overlay window. */
  3098.   GLXwinset (XtDisplay (w), overlayWindow (w));
  3099.   viewport
  3100.     (0, (Screencoord)pv->dv_width - 1, 0, (Screencoord)pv->dv_height - 1);
  3101. #endif
  3102.   
  3103.   /* We get a redraw callback here. */
  3104.   
  3105.   return;
  3106. }
  3107.  
  3108.  
  3109.  
  3110. /* -------------------------- win_open_polyview --------------------------- */
  3111. #ifdef __sgi
  3112. static GLXconfig polyviewGlxConfig[] =
  3113. {
  3114.   { GLX_NORMAL, GLX_DOUBLE, TRUE },
  3115.   { GLX_NORMAL, GLX_RGB, TRUE },
  3116.   { GLX_NORMAL, GLX_ZSIZE, GLX_NOCONFIG },
  3117.   { GLX_OVERLAY, GLX_BUFSIZE, 2},
  3118.   { 0, 0, 0 },
  3119. };
  3120. #endif /* __sgi */
  3121.  
  3122. int win_open_polyview(state_t *state, window_t *win, char *name)
  3123. {
  3124.   /* Just for the hell of it, we use the 'win' pointer passed in. */
  3125.   /* window_t *win; */
  3126.   polyview_t *pv;
  3127.   Widget button_form, drawing_frame;
  3128.   char line[MAXLINELEN];
  3129.   
  3130.   /* Uh oh, what if we got an unnamed window? */
  3131.   if (name[0] == '\0')
  3132.     name = "Unnamed";
  3133.   
  3134.   /* Create a new win */
  3135.   win = add_window
  3136.     (state, name, POLYVIEW, init_polyview, redraw_polyview, animate_polyview,
  3137.      event_polyview, notify_polyview, destroy_polyview);
  3138.   
  3139.   /* Add polyview structure to the new window. */
  3140.   add_poly(state, win);
  3141.   
  3142.   /* Grab the polyview struct from the window struct.  We have created
  3143.      it in add_poly above. */
  3144.   pv = (polyview_t *)WIN_IMAGE(win);
  3145.   
  3146.   /* Choose a uniqid and create the window. */
  3147.   win->id = XmxMakeNewUniqid ();
  3148.   XmxSetUniqid (win->id);
  3149.   sprintf (line, "Polyview 3.1: %s\0", name);
  3150.   win->base = XmxMakeFormDialog (state->base, line);
  3151.   
  3152.   /* Identify the window for debugging purposes. */
  3153.   win->debug_str = "***Polyview Window";
  3154.   
  3155.   /* Make the menubar first. */
  3156.   pv->menubar = XmxRMakeMenubar (win->base, PviewMenu);
  3157.   
  3158.   /* Initial menubar options. */
  3159.   pv->current_select_token = PV_PVIEW_SELECT_FACES;
  3160.   XmxRSetToggleState (pv->menubar, pv->current_select_token, XmxSet);
  3161.   
  3162.   /* Make button_form and buttons. */
  3163.   XmxSetArg (XmNverticalSpacing, 5);
  3164.   XmxSetArg (XmNhorizontalSpacing, 10);
  3165.   button_form = XmxMakeForm (win->base);
  3166.   
  3167.   pv->active = XmxMakeToggleButton 
  3168.     (button_form, "Active", GUIpolyviewWindowCB, PV_PVIEW_ACTIVE);
  3169.   pv->dtmlockout = XmxMakeToggleButton 
  3170.     (button_form, "Private", GUIpolyviewWindowCB, PV_PVIEW_PRIVATE);
  3171.   XmxSetSensitive (pv->dtmlockout, XmxUnsensitive);
  3172.   XmxSetToggleButton (pv->active, XmxSet);
  3173.   XmxSetToggleButton (pv->dtmlockout, XmxUnset);
  3174.   
  3175.   pv->blast = XmxMakePushButton 
  3176.     (button_form, "Blast Image", GUIpolyviewWindowCB, PV_PVIEW_BLAST);
  3177.   
  3178.   /* Constraints for button_form. */
  3179.   XmxSetConstraints 
  3180.     (pv->active, XmATTACH_FORM, XmATTACH_FORM, XmATTACH_FORM, XmATTACH_NONE,
  3181.      NULL, NULL, NULL, NULL);
  3182.   XmxSetConstraints
  3183.     (pv->blast, XmATTACH_FORM, XmATTACH_FORM, XmATTACH_WIDGET, 
  3184.      XmATTACH_NONE, NULL, NULL, pv->active, NULL);
  3185.   XmxSetConstraints 
  3186.     (pv->dtmlockout, XmATTACH_FORM, XmATTACH_FORM, XmATTACH_NONE, 
  3187.      XmATTACH_FORM, NULL, NULL, NULL, NULL);
  3188.   
  3189.   /* Make the frame for the drawing volume. */
  3190.   drawing_frame = XmxMakeFrame (win->base, XmxShadowOut);
  3191.   
  3192.   /* Make the drawing volume itself. */
  3193.   pv->dv_width = win->width = 640;
  3194.   pv->dv_height = win->height = 512;
  3195.   win->cx = win->width / 2;
  3196.   win->cy = win->height / 2;
  3197.   
  3198. #ifdef __sgi
  3199.   if (getgdesc (GD_BITS_OVER_SNG_CMODE) < 2)
  3200.     use_pups = TRUE;
  3201.   
  3202.   if (use_pups)
  3203.     polyviewGlxConfig[3].buffer = GLX_POPUP;
  3204.   
  3205.   XmxSetArg (use_pups ? GlxNusePopup : GlxNuseOverlay, TRUE);
  3206.   
  3207.   pv->drawing_volume = XmxMakeDrawingVolume
  3208.     (drawing_frame, pv->dv_width, pv->dv_height, polyviewGlxConfig, 
  3209.      GUIpviewRedrawCB, GUIpviewResizeCB, GUIpviewGinitCB);
  3210.   
  3211.   XtAddCallback 
  3212.     (pv->drawing_volume,
  3213.      use_pups ? GlxNpopupExposeCallback : GlxNoverlayExposeCallback,
  3214.      overlayExposeCB, 0);
  3215. #endif
  3216.   
  3217. #ifdef _IBMR2
  3218.   pv->drawing_volume = XmxMakeDrawingVolume
  3219.     (drawing_frame, pv->dv_width, pv->dv_height,
  3220.      GUIpviewRedrawCB, GUIpviewResizeCB, GUIpviewGinitCB);
  3221. #endif
  3222.   
  3223.   /* Add the event handler for button presses.  The buttonpress
  3224.      handler spawns off motion and release handlers as necessary. */
  3225.   XmxAddEventHandler
  3226.     (pv->drawing_volume, ButtonPressMask, GUIpolyviewButtonPressHandler, 0);
  3227.   
  3228. #ifdef __sgi
  3229.   /* !@#%!@#%!@#%!@# IBM */
  3230.   /* Use the input callback for keyboard events. */
  3231.   XmxAddCallback (pv->drawing_volume, XmNinputCallback, GUIpviewInputCB, 0);
  3232. #endif
  3233.   
  3234.   /* Constraints for base. */
  3235.   XmxSetConstraints 
  3236.     (pv->menubar->base, XmATTACH_FORM, XmATTACH_NONE, XmATTACH_FORM, 
  3237.      XmATTACH_FORM, NULL, NULL, NULL, NULL);
  3238.   XmxSetConstraints 
  3239.     (button_form, XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_FORM,
  3240.      pv->menubar->base, NULL, NULL, NULL);
  3241.   XmxSetConstraints 
  3242.     (drawing_frame, XmATTACH_WIDGET, XmATTACH_FORM, XmATTACH_FORM, 
  3243.      XmATTACH_FORM, button_form, NULL, NULL, NULL);
  3244.   
  3245.   /* Set the default drawing function.  Default rotation, scaling, and */
  3246.   /* translation are maintained. */
  3247.   WIN_DRAW(win) = draw_edges;
  3248.   XFO_USED(WIN_ROT(win)) = TRUE;
  3249.   XFO_USED(WIN_SCL(win)) = TRUE;
  3250.   XFO_USED(WIN_TRN(win)) = TRUE;
  3251.   
  3252.   XmxManageRemanage (win->base);
  3253.   
  3254.   GUIpviewResetRender (state, win);
  3255.   GUIpviewResetProps (state, win);
  3256.   
  3257.   add_palette(state, win, NULL);
  3258.   
  3259.   GUIpaletteResetBackdrop (state, win);
  3260.   GUIpaletteResetPresets (state);
  3261.   
  3262.   win_activate(state, win);
  3263.   
  3264.   return ST_OKAY;
  3265. }
  3266.